From 35938133d62e2df6defd22ebc94fb858b5e5434b Mon Sep 17 00:00:00 2001 From: dufyfduck Date: Sun, 1 Feb 2026 00:02:35 +0100 Subject: [PATCH] added backup and email client --- README.md | 258 +- backend/.gitignore | 28 + .../stressfreiEmail.controller.d.ts | 1 + .../stressfreiEmail.controller.d.ts.map | 2 +- .../controllers/stressfreiEmail.controller.js | 24 + .../stressfreiEmail.controller.js.map | 2 +- backend/dist/index.js | 2 + backend/dist/index.js.map | 2 +- backend/dist/middleware/auth.d.ts | 2 +- backend/dist/middleware/auth.d.ts.map | 2 +- backend/dist/middleware/auth.js | 39 +- backend/dist/middleware/auth.js.map | 2 +- .../dist/routes/appSetting.routes.d.ts.map | 2 +- backend/dist/routes/appSetting.routes.js | 33 + backend/dist/routes/appSetting.routes.js.map | 2 +- .../routes/contractCategory.routes.d.ts.map | 2 +- .../dist/routes/contractCategory.routes.js | 8 +- .../routes/contractCategory.routes.js.map | 2 +- .../routes/stressfreiEmail.routes.d.ts.map | 2 +- backend/dist/routes/stressfreiEmail.routes.js | 2 + .../dist/routes/stressfreiEmail.routes.js.map | 2 +- backend/dist/services/contract.service.d.ts | 14 + .../dist/services/contract.service.d.ts.map | 2 +- backend/dist/services/contract.service.js | 33 +- backend/dist/services/contract.service.js.map | 2 +- backend/dist/services/customer.service.d.ts | 2 + .../dist/services/customer.service.d.ts.map | 2 +- backend/dist/services/customer.service.js | 4 + backend/dist/services/customer.service.js.map | 2 +- .../emailProvider/emailProviderService.d.ts | 70 +- .../emailProviderService.d.ts.map | 2 +- .../emailProvider/emailProviderService.js | 157 + .../emailProvider/emailProviderService.js.map | 2 +- .../services/emailProvider/pleskProvider.d.ts | 5 +- .../emailProvider/pleskProvider.d.ts.map | 2 +- .../services/emailProvider/pleskProvider.js | 127 +- .../emailProvider/pleskProvider.js.map | 2 +- .../dist/services/emailProvider/types.d.ts | 28 + .../services/emailProvider/types.d.ts.map | 2 +- .../services/stressfreiEmail.service.d.ts | 62 +- .../services/stressfreiEmail.service.d.ts.map | 2 +- .../dist/services/stressfreiEmail.service.js | 192 +- .../services/stressfreiEmail.service.js.map | 2 +- backend/dist/services/user.service.d.ts | 2 + backend/dist/services/user.service.d.ts.map | 2 +- backend/dist/services/user.service.js | 38 +- backend/dist/services/user.service.js.map | 2 +- backend/dist/types/index.d.ts | 1 + backend/dist/types/index.d.ts.map | 2 +- backend/node_modules/.package-lock.json | 1387 +++++++ backend/node_modules/.prisma/client/edge.js | 57 +- .../.prisma/client/index-browser.js | 50 + .../node_modules/.prisma/client/index.d.ts | 3270 ++++++++++++++++- backend/node_modules/.prisma/client/index.js | 57 +- .../node_modules/.prisma/client/package.json | 2 +- .../node_modules/.prisma/client/schema.prisma | 134 +- backend/node_modules/.prisma/client/wasm.js | 50 + backend/package-lock.json | 1396 +++++++ backend/package.json | 13 +- backend/prisma/add-email-delete-permission.ts | 88 + backend/prisma/backup-data.ts | 114 + backend/prisma/backups/.gitkeep | 0 .../migration.sql | 180 + .../migration.sql | 2 + backend/prisma/restore-data.ts | 486 +++ backend/prisma/schema.prisma | 132 +- backend/prisma/seed.ts | 214 +- backend/src/controllers/backup.controller.ts | 169 + .../src/controllers/cachedEmail.controller.ts | 805 ++++ .../controllers/stressfreiEmail.controller.ts | 23 + backend/src/index.ts | 2 + backend/src/middleware/auth.ts | 48 +- backend/src/routes/appSetting.routes.ts | 74 + backend/src/routes/cachedEmail.routes.ts | 237 ++ backend/src/routes/contractCategory.routes.ts | 9 +- backend/src/routes/stressfreiEmail.routes.ts | 3 + backend/src/services/backup.service.ts | 1186 ++++++ backend/src/services/cachedEmail.service.ts | 957 +++++ .../emailProvider/emailProviderService.ts | 188 + .../services/emailProvider/pleskProvider.ts | 136 + backend/src/services/emailProvider/types.ts | 45 +- backend/src/services/imapService.ts | 825 +++++ backend/src/services/smtpService.ts | 304 ++ .../src/services/stressfreiEmail.service.ts | 243 +- backend/src/services/user.service.ts | 42 +- backend/src/types/index.ts | 1 + backend/src/utils/passwordGenerator.ts | 101 + .../bank-cards/1768955872666-860459988.pdf | Bin 3009784 -> 0 bytes .../1769259293397-35099879.pdf | Bin 36358 -> 0 bytes .../documents/1768933724293-891175977.pdf | Bin 155515 -> 0 bytes .../documents/1768934990480-244507721.pdf | Bin 601902 -> 0 bytes .../documents/1768955942689-251727350.pdf | Bin 3009784 -> 0 bytes frontend/dist/assets/index-B7w5p8ZY.css | 1 + frontend/dist/assets/index-CitfypIw.js | 678 ++++ frontend/dist/assets/index-Cpkp9CHh.js | 408 -- frontend/dist/assets/index-_pEZoPeF.css | 1 - frontend/dist/index.html | 4 +- frontend/node_modules/.package-lock.json | 27 +- .../node_modules/.vite/deps/_metadata.json | 32 +- .../.vite/deps/react-hot-toast.js | 486 +++ .../.vite/deps/react-hot-toast.js.map | 7 + frontend/node_modules/goober/LICENSE | 21 + frontend/node_modules/goober/README.md | 857 +++++ frontend/node_modules/goober/dist/goober.cjs | 1 + .../node_modules/goober/dist/goober.esm.js | 1 + .../node_modules/goober/dist/goober.modern.js | 1 + .../node_modules/goober/dist/goober.umd.js | 1 + .../goober/global/dist/goober-global.cjs | 1 + .../goober/global/dist/goober-global.esm.js | 1 + .../global/dist/goober-global.modern.js | 1 + .../goober/global/dist/goober-global.umd.js | 1 + .../node_modules/goober/global/global.d.ts | 25 + .../node_modules/goober/global/package.json | 42 + .../__snapshots__/integration.test.js.snap | 9 + .../global/src/__tests__/global.test.js | 22 + .../global/src/__tests__/integration.test.js | 56 + .../node_modules/goober/global/src/index.js | 26 + frontend/node_modules/goober/goober.d.ts | 101 + frontend/node_modules/goober/macro/index.js | 43 + .../node_modules/goober/macro/package.json | 22 + frontend/node_modules/goober/package.json | 154 + .../node_modules/goober/prefixer/README.md | 20 + .../goober/prefixer/autoprefixer.d.ts | 7 + .../prefixer/dist/goober-autoprefixer.cjs | 1 + .../prefixer/dist/goober-autoprefixer.esm.js | 1 + .../dist/goober-autoprefixer.modern.js | 1 + .../prefixer/dist/goober-autoprefixer.umd.js | 1 + .../node_modules/goober/prefixer/package.json | 44 + .../node_modules/goober/prefixer/src/index.js | 28 + .../dist/goober-should-forward-prop.cjs | 1 + .../dist/goober-should-forward-prop.esm.js | 1 + .../dist/goober-should-forward-prop.modern.js | 1 + .../dist/goober-should-forward-prop.umd.js | 1 + .../goober/should-forward-prop/package.json | 41 + .../should-forward-prop.d.ts | 9 + .../src/__tests__/shouldForwardProp.js | 25 + .../goober/should-forward-prop/src/index.js | 19 + .../goober/src/__tests__/css.test.js | 114 + .../goober/src/__tests__/index.test.js | 14 + .../goober/src/__tests__/integrations.test.js | 246 ++ .../goober/src/__tests__/styled.test.js | 159 + .../goober/src/core/__tests__/astish.test.js | 219 ++ .../goober/src/core/__tests__/compile.test.js | 70 + .../src/core/__tests__/get-sheet.test.js | 70 + .../goober/src/core/__tests__/hash.test.js | 126 + .../goober/src/core/__tests__/parse.test.js | 327 ++ .../goober/src/core/__tests__/to-hash.test.js | 17 + .../goober/src/core/__tests__/update.test.js | 64 + .../node_modules/goober/src/core/astish.js | 28 + .../node_modules/goober/src/core/compile.js | 41 + .../node_modules/goober/src/core/get-sheet.js | 27 + frontend/node_modules/goober/src/core/hash.js | 67 + .../node_modules/goober/src/core/parse.js | 60 + .../node_modules/goober/src/core/to-hash.js | 15 + .../node_modules/goober/src/core/update.js | 25 + frontend/node_modules/goober/src/css.js | 40 + frontend/node_modules/goober/src/index.js | 3 + frontend/node_modules/goober/src/styled.js | 73 + frontend/node_modules/goober/typings.json | 5 + frontend/node_modules/react-hot-toast/LICENSE | 21 + .../node_modules/react-hot-toast/README.md | 72 + .../react-hot-toast/dist/index.d.ts | 130 + .../react-hot-toast/dist/index.js | 179 + .../react-hot-toast/dist/index.js.map | 1 + .../react-hot-toast/dist/index.mjs | 179 + .../react-hot-toast/dist/index.mjs.map | 1 + .../react-hot-toast/headless/index.d.ts | 93 + .../react-hot-toast/headless/index.js | 2 + .../react-hot-toast/headless/index.js.map | 1 + .../react-hot-toast/headless/index.mjs | 2 + .../react-hot-toast/headless/index.mjs.map | 1 + .../node_modules/react-hot-toast/package.json | 103 + .../src/components/checkmark.tsx | 61 + .../react-hot-toast/src/components/error.tsx | 71 + .../react-hot-toast/src/components/loader.tsx | 26 + .../src/components/toast-bar.tsx | 111 + .../src/components/toast-icon.tsx | 77 + .../src/components/toaster.tsx | 143 + .../react-hot-toast/src/core/store.ts | 232 ++ .../react-hot-toast/src/core/toast.ts | 159 + .../react-hot-toast/src/core/types.ts | 97 + .../react-hot-toast/src/core/use-toaster.ts | 145 + .../react-hot-toast/src/core/utils.ts | 19 + .../react-hot-toast/src/headless/index.ts | 21 + .../node_modules/react-hot-toast/src/index.ts | 13 + frontend/package-lock.json | 28 +- frontend/package.json | 1 + frontend/src/App.tsx | 2 + .../email/AssignToContractModal.tsx | 174 + .../components/email/ComposeEmailModal.tsx | 340 ++ .../email/ContractEmailsSection.tsx | 391 ++ .../src/components/email/EmailClientTab.tsx | 394 ++ frontend/src/components/email/EmailDetail.tsx | 458 +++ frontend/src/components/email/EmailList.tsx | 276 ++ .../src/components/email/TrashEmailList.tsx | 248 ++ frontend/src/components/email/index.ts | 6 + frontend/src/components/ui/Card.tsx | 4 +- frontend/src/main.tsx | 23 + frontend/src/pages/Settings.tsx | 19 +- .../src/pages/contracts/ContractDetail.tsx | 9 + frontend/src/pages/contracts/ContractForm.tsx | 11 + .../src/pages/customers/CustomerDetail.tsx | 293 +- .../pages/settings/ContractCategoryList.tsx | 12 +- .../src/pages/settings/DatabaseBackup.tsx | 478 +++ .../src/pages/settings/EmailProviders.tsx | 85 + frontend/src/pages/users/UserList.tsx | 45 +- frontend/src/services/api.ts | 281 +- frontend/src/types/index.ts | 2 + plesktest/add_sasl.sh | 22 + plesktest/docker-compose.yml | 23 +- plesktest/get_postfix_logs.sh | 18 + plesktest/seek_atuh_socket.sh | 13 + plesktest/setup-domain.sh | 68 + plesktest/test_port_587smtp.sh | 16 + test pdf datei.pdf | Bin 0 -> 8669 bytes 215 files changed, 24211 insertions(+), 742 deletions(-) create mode 100644 backend/.gitignore create mode 100644 backend/prisma/add-email-delete-permission.ts create mode 100644 backend/prisma/backup-data.ts create mode 100644 backend/prisma/backups/.gitkeep create mode 100644 backend/prisma/migrations/20260130231219_add_email_trash_fields/migration.sql create mode 100644 backend/prisma/migrations/20260130233909_add_token_invalidation/migration.sql create mode 100644 backend/prisma/restore-data.ts create mode 100644 backend/src/controllers/backup.controller.ts create mode 100644 backend/src/controllers/cachedEmail.controller.ts create mode 100644 backend/src/routes/cachedEmail.routes.ts create mode 100644 backend/src/services/backup.service.ts create mode 100644 backend/src/services/cachedEmail.service.ts create mode 100644 backend/src/services/imapService.ts create mode 100644 backend/src/services/smtpService.ts create mode 100644 backend/src/utils/passwordGenerator.ts delete mode 100644 backend/uploads/bank-cards/1768955872666-860459988.pdf delete mode 100644 backend/uploads/cancellation-letters/1769259293397-35099879.pdf delete mode 100644 backend/uploads/documents/1768933724293-891175977.pdf delete mode 100644 backend/uploads/documents/1768934990480-244507721.pdf delete mode 100644 backend/uploads/documents/1768955942689-251727350.pdf create mode 100644 frontend/dist/assets/index-B7w5p8ZY.css create mode 100644 frontend/dist/assets/index-CitfypIw.js delete mode 100644 frontend/dist/assets/index-Cpkp9CHh.js delete mode 100644 frontend/dist/assets/index-_pEZoPeF.css create mode 100644 frontend/node_modules/.vite/deps/react-hot-toast.js create mode 100644 frontend/node_modules/.vite/deps/react-hot-toast.js.map create mode 100644 frontend/node_modules/goober/LICENSE create mode 100644 frontend/node_modules/goober/README.md create mode 100644 frontend/node_modules/goober/dist/goober.cjs create mode 100644 frontend/node_modules/goober/dist/goober.esm.js create mode 100644 frontend/node_modules/goober/dist/goober.modern.js create mode 100644 frontend/node_modules/goober/dist/goober.umd.js create mode 100644 frontend/node_modules/goober/global/dist/goober-global.cjs create mode 100644 frontend/node_modules/goober/global/dist/goober-global.esm.js create mode 100644 frontend/node_modules/goober/global/dist/goober-global.modern.js create mode 100644 frontend/node_modules/goober/global/dist/goober-global.umd.js create mode 100644 frontend/node_modules/goober/global/global.d.ts create mode 100644 frontend/node_modules/goober/global/package.json create mode 100644 frontend/node_modules/goober/global/src/__tests__/__snapshots__/integration.test.js.snap create mode 100644 frontend/node_modules/goober/global/src/__tests__/global.test.js create mode 100644 frontend/node_modules/goober/global/src/__tests__/integration.test.js create mode 100644 frontend/node_modules/goober/global/src/index.js create mode 100644 frontend/node_modules/goober/goober.d.ts create mode 100644 frontend/node_modules/goober/macro/index.js create mode 100644 frontend/node_modules/goober/macro/package.json create mode 100644 frontend/node_modules/goober/package.json create mode 100644 frontend/node_modules/goober/prefixer/README.md create mode 100644 frontend/node_modules/goober/prefixer/autoprefixer.d.ts create mode 100644 frontend/node_modules/goober/prefixer/dist/goober-autoprefixer.cjs create mode 100644 frontend/node_modules/goober/prefixer/dist/goober-autoprefixer.esm.js create mode 100644 frontend/node_modules/goober/prefixer/dist/goober-autoprefixer.modern.js create mode 100644 frontend/node_modules/goober/prefixer/dist/goober-autoprefixer.umd.js create mode 100644 frontend/node_modules/goober/prefixer/package.json create mode 100644 frontend/node_modules/goober/prefixer/src/index.js create mode 100644 frontend/node_modules/goober/should-forward-prop/dist/goober-should-forward-prop.cjs create mode 100644 frontend/node_modules/goober/should-forward-prop/dist/goober-should-forward-prop.esm.js create mode 100644 frontend/node_modules/goober/should-forward-prop/dist/goober-should-forward-prop.modern.js create mode 100644 frontend/node_modules/goober/should-forward-prop/dist/goober-should-forward-prop.umd.js create mode 100644 frontend/node_modules/goober/should-forward-prop/package.json create mode 100644 frontend/node_modules/goober/should-forward-prop/should-forward-prop.d.ts create mode 100644 frontend/node_modules/goober/should-forward-prop/src/__tests__/shouldForwardProp.js create mode 100644 frontend/node_modules/goober/should-forward-prop/src/index.js create mode 100644 frontend/node_modules/goober/src/__tests__/css.test.js create mode 100644 frontend/node_modules/goober/src/__tests__/index.test.js create mode 100644 frontend/node_modules/goober/src/__tests__/integrations.test.js create mode 100644 frontend/node_modules/goober/src/__tests__/styled.test.js create mode 100644 frontend/node_modules/goober/src/core/__tests__/astish.test.js create mode 100644 frontend/node_modules/goober/src/core/__tests__/compile.test.js create mode 100644 frontend/node_modules/goober/src/core/__tests__/get-sheet.test.js create mode 100644 frontend/node_modules/goober/src/core/__tests__/hash.test.js create mode 100644 frontend/node_modules/goober/src/core/__tests__/parse.test.js create mode 100644 frontend/node_modules/goober/src/core/__tests__/to-hash.test.js create mode 100644 frontend/node_modules/goober/src/core/__tests__/update.test.js create mode 100644 frontend/node_modules/goober/src/core/astish.js create mode 100644 frontend/node_modules/goober/src/core/compile.js create mode 100644 frontend/node_modules/goober/src/core/get-sheet.js create mode 100644 frontend/node_modules/goober/src/core/hash.js create mode 100644 frontend/node_modules/goober/src/core/parse.js create mode 100644 frontend/node_modules/goober/src/core/to-hash.js create mode 100644 frontend/node_modules/goober/src/core/update.js create mode 100644 frontend/node_modules/goober/src/css.js create mode 100644 frontend/node_modules/goober/src/index.js create mode 100644 frontend/node_modules/goober/src/styled.js create mode 100644 frontend/node_modules/goober/typings.json create mode 100644 frontend/node_modules/react-hot-toast/LICENSE create mode 100644 frontend/node_modules/react-hot-toast/README.md create mode 100644 frontend/node_modules/react-hot-toast/dist/index.d.ts create mode 100644 frontend/node_modules/react-hot-toast/dist/index.js create mode 100644 frontend/node_modules/react-hot-toast/dist/index.js.map create mode 100644 frontend/node_modules/react-hot-toast/dist/index.mjs create mode 100644 frontend/node_modules/react-hot-toast/dist/index.mjs.map create mode 100644 frontend/node_modules/react-hot-toast/headless/index.d.ts create mode 100644 frontend/node_modules/react-hot-toast/headless/index.js create mode 100644 frontend/node_modules/react-hot-toast/headless/index.js.map create mode 100644 frontend/node_modules/react-hot-toast/headless/index.mjs create mode 100644 frontend/node_modules/react-hot-toast/headless/index.mjs.map create mode 100644 frontend/node_modules/react-hot-toast/package.json create mode 100644 frontend/node_modules/react-hot-toast/src/components/checkmark.tsx create mode 100644 frontend/node_modules/react-hot-toast/src/components/error.tsx create mode 100644 frontend/node_modules/react-hot-toast/src/components/loader.tsx create mode 100644 frontend/node_modules/react-hot-toast/src/components/toast-bar.tsx create mode 100644 frontend/node_modules/react-hot-toast/src/components/toast-icon.tsx create mode 100644 frontend/node_modules/react-hot-toast/src/components/toaster.tsx create mode 100644 frontend/node_modules/react-hot-toast/src/core/store.ts create mode 100644 frontend/node_modules/react-hot-toast/src/core/toast.ts create mode 100644 frontend/node_modules/react-hot-toast/src/core/types.ts create mode 100644 frontend/node_modules/react-hot-toast/src/core/use-toaster.ts create mode 100644 frontend/node_modules/react-hot-toast/src/core/utils.ts create mode 100644 frontend/node_modules/react-hot-toast/src/headless/index.ts create mode 100644 frontend/node_modules/react-hot-toast/src/index.ts create mode 100644 frontend/src/components/email/AssignToContractModal.tsx create mode 100644 frontend/src/components/email/ComposeEmailModal.tsx create mode 100644 frontend/src/components/email/ContractEmailsSection.tsx create mode 100644 frontend/src/components/email/EmailClientTab.tsx create mode 100644 frontend/src/components/email/EmailDetail.tsx create mode 100644 frontend/src/components/email/EmailList.tsx create mode 100644 frontend/src/components/email/TrashEmailList.tsx create mode 100644 frontend/src/components/email/index.ts create mode 100644 frontend/src/pages/settings/DatabaseBackup.tsx create mode 100755 plesktest/add_sasl.sh create mode 100755 plesktest/get_postfix_logs.sh create mode 100755 plesktest/seek_atuh_socket.sh create mode 100755 plesktest/test_port_587smtp.sh create mode 100644 test pdf datei.pdf diff --git a/README.md b/README.md index 1c3ef9c3..8ed8c444 100644 --- a/README.md +++ b/README.md @@ -292,76 +292,216 @@ fetch('/api/developer/setup', { method: 'POST' }).then(r => r.json()).then(conso # Danach ausloggen und neu einloggen ``` -## Geplante Features +## Vertragstypen -### E-Mail-Client Integration +### Standard-Vertragstypen -Ein integrierter E-Mail-Client pro Kunde mit den folgenden Funktionen: +Folgende Vertragstypen werden bei Installation/Factory-Reset automatisch angelegt: -#### Konzept +| Code | Name | Icon | Farbe | +|------|------|------|-------| +| ELECTRICITY | Strom | Zap | #FFC107 | +| GAS | Gas | Flame | #FF5722 | +| DSL | DSL | Wifi | #2196F3 | +| FIBER | Glasfaser | Cable | #9C27B0 | +| CABLE | Kabel Internet (Coax) | Cable | #00BCD4 | +| MOBILE | Mobilfunk | Smartphone | #4CAF50 | +| TV | TV | Tv | #E91E63 | +| CAR_INSURANCE | KFZ-Versicherung | Car | #607D8B | -- **E-Mail-Tab in Kundenansicht**: Zeigt alle E-Mails des Kunden via IMAP an -- **Mehrere E-Mail-Konten**: Dropdown zur Auswahl zwischen verschiedenen `@stressfrei-wechseln.de` Adressen des Kunden -- **E-Mails schreiben**: Neue E-Mails verfassen und Antworten auf bestehende E-Mails -- **Versand vom ausgewählten Konto**: SMTP-Versand über die gewählte Stressfrei-Wechseln Adresse -- **Zuordnung zu Verträgen**: Manuelles Zuordnen von E-Mails zu Verträgen -- **E-Mail-Tab in Vertragsansicht**: Zeigt nur dem Vertrag zugeordnete E-Mails (Postfach-Ansicht), mit Antworten/Schreiben-Funktion +> **Hinweis:** Vertragstypen können nur von Benutzern mit **Entwicklerzugriff** geändert werden, da Änderungen auch Anpassungen an den Formularen erfordern. -#### Technische Umsetzung +### Vertragstyp-spezifische Felder -1. **IMAP/SMTP-Zugangsdaten speichern** - - Beim Erstellen einer StressfreiEmail werden die Zugangsdaten vom Email-Provider (Plesk) zurückgegeben - - Diese werden verschlüsselt in der Datenbank gespeichert (wie bereits bei Portal-Zugangsdaten) - - StressfreiEmail-Tabelle erweitern um: `imapServer`, `imapPort`, `smtpServer`, `smtpPort`, `emailPassword` (verschlüsselt) +Je nach Vertragstyp werden unterschiedliche Felder im Formular angezeigt: -2. **Backend: IMAP-Service** - - IMAP-Client zum Abrufen von E-Mails (z.B. `imap-simple` oder `imapflow`) - - Endpunkte: - - `GET /api/customers/:id/emails` - E-Mails für Kunde abrufen - - `GET /api/emails/:id` - Einzelne E-Mail mit Body - - `POST /api/emails/send` - E-Mail senden (SMTP) - - `PUT /api/emails/:id/assign` - E-Mail einem Vertrag zuordnen +#### Strom & Gas (ELECTRICITY, GAS) -3. **Frontend: E-Mail-Tab (Kundenansicht)** - - Neuer Tab in CustomerDetail: "E-Mails" - - Dropdown oben: Auswahl der StressfreiEmail-Adresse - - Liste der E-Mails (Betreff, Absender, Datum) - - Detail-Ansicht beim Klick - - "Neue E-Mail" und "Antworten" Buttons - - "Vertrag zuordnen" Dropdown in E-Mail-Detail +- Zähler-Auswahl +- Jahresverbrauch (kWh/m³) +- Grundpreis, Arbeitspreis +- Bonus +- Vorversorger, Kundennummer beim Vorversorger -4. **Frontend: E-Mail-Tab (Vertragsansicht)** - - Neuer Tab in ContractDetail: "E-Mails" - - Zeigt nur E-Mails die diesem Vertrag zugeordnet sind - - Gleiche Funktionalität wie in Kundenansicht: - - Liste der zugeordneten E-Mails - - Detail-Ansicht beim Klick - - "Neue E-Mail" und "Antworten" Buttons - - Versand erfolgt über die StressfreiEmail-Adresse des Kunden +#### Internet (DSL, CABLE, FIBER) -5. **Datenbank** - ```prisma - model CustomerEmail { - id Int @id @default(autoincrement()) - customerId Int - customer Customer @relation(...) - stressfreiEmailId Int - stressfreiEmail StressfreiEmail @relation(...) - contractId Int? // Optionale Zuordnung zu Vertrag - contract Contract? @relation(...) - messageId String @unique // IMAP Message-ID - subject String - fromAddress String - toAddress String - date DateTime - isRead Boolean @default(false) - folder String // INBOX, Sent, etc. - createdAt DateTime @default(now()) - } - ``` +- Download/Upload (Mbit/s) +- Router Modell, Seriennummer +- Installationsdatum +- Benutzername, Passwort +- Rufnummern mit SIP-Zugangsdaten -#### Status -- [ ] Noch nicht implementiert - Plan für zukünftige Version +| Vertragstyp | Zusatzfeld | +|-------------|------------| +| **Glasfaser (FIBER)** | Home-ID | + +#### Mobilfunk (MOBILE) + +- Datenvolumen (GB) +- Inklusiv-Minuten, Inklusiv-SMS +- Gerät-Modell, IMEI +- Multisim-Checkbox +- SIM-Karten (dynamisch erweiterbar): + - Rufnummer, SIM-Kartennummer (ICCID) + - PIN, PUK (verschlüsselt) + - Multisim-Flag, Hauptkarte-Flag + +> **Hinweis Multisim:** Nicht buchbar bei Klarmobil, Congstar, Otelo. Benötigt Freenet oder vergleichbar. + +#### TV + +- Receiver Modell +- Smartcard-Nummer +- Paket/Angebot + +#### KFZ-Versicherung (CAR_INSURANCE) + +- Kennzeichen, HSN, TSN, FIN/VIN +- Fahrzeugtyp, Erstzulassung +- SF-Klasse (Schadenfreiheitsklasse) +- Versicherungsart (Haftpflicht/Teilkasko/Vollkasko) +- Selbstbeteiligungen (Teilkasko, Vollkasko) +- Versicherungsscheinnummer +- Vorversicherer + +### Standard-Anbieter + +Folgende Anbieter werden bei Installation/Factory-Reset automatisch angelegt: + +| Anbieter | Portal-URL | +|----------|------------| +| Vodafone | https://www.vodafone.de/meinvodafone/account/login | +| Klarmobil | https://www.klarmobil.de/login | +| Otelo | https://www.otelo.de/mein-otelo/login | +| Congstar | https://www.congstar.de/login/ | +| Telekom | https://www.telekom.de/kundencenter/startseite | +| O2 | https://www.o2online.de/ecare/selfcare | +| 1&1 | https://control-center.1und1.de/ | + +### Anbieter-spezifische Felder + +Einige Felder werden nur bei bestimmten Anbietern angezeigt: + +| Anbieter | Vertragstyp | Zusatzfeld | +|----------|-------------|------------| +| **Vodafone** | DSL, Kabel Internet | Aktivierungscode | + +> **Hinweis Multisim:** Bei Klarmobil, Congstar und Otelo ist Multisim **nicht** buchbar. Dafür wird Freenet oder ein vergleichbarer Anbieter benötigt. + +## E-Mail-Client + +Ein vollständig integrierter E-Mail-Client pro Kunde mit IMAP-Empfang und SMTP-Versand. + +### Funktionen + +#### E-Mails lesen & verwalten +- **E-Mail-Tab in Kundenansicht** mit Ordnern: Posteingang, Gesendet, Papierkorb +- **Mehrere E-Mail-Konten** pro Kunde (Dropdown zur Auswahl) +- **E-Mail-Detailansicht** mit HTML/Text-Body, Absender, Empfänger, CC, Datum +- **Gelesen/Ungelesen** markieren +- **Favoriten** (Stern) für wichtige E-Mails +- **Papierkorb** mit Wiederherstellen und endgültigem Löschen + +#### E-Mails schreiben +- **Neue E-Mail verfassen** mit An, CC, Betreff, Text +- **Antworten** mit zitiertem Originaltext +- **Dateianhänge** (max. 10 MB pro Datei, 25 MB gesamt) +- **SMTP-Versand** über die gewählte StressfreiEmail-Adresse + +#### Vertragszuordnung +- **E-Mails zu Verträgen zuordnen** für bessere Nachverfolgung +- **E-Mail-Tab in Vertragsansicht** zeigt nur zugeordnete E-Mails +- **Automatische Zuordnung** bei Versand aus Vertragskontext +- **Manuelle Zuordnung** über Suchfeld und Vertragsauswahl + +#### Anhänge +- **Anhangsliste** in E-Mail-Detail +- **Download** einzelner Anhänge +- **Inline-Ansicht** (im Browser öffnen) + +### Technische Details + +#### Backend-Services +| Service | Beschreibung | +|---------|--------------| +| `imapService.ts` | IMAP-Client (ImapFlow) für E-Mail-Empfang | +| `smtpService.ts` | SMTP-Client (Nodemailer) für E-Mail-Versand | +| `cachedEmail.service.ts` | E-Mail-Caching, Synchronisation, Zuordnung | + +#### API-Endpunkte +``` +GET /api/customers/:id/emails # E-Mails für Kunde +GET /api/contracts/:id/emails # E-Mails für Vertrag +GET /api/emails/:id # Einzelne E-Mail mit Body +POST /api/stressfrei-emails/:id/sync # IMAP-Synchronisation +POST /api/stressfrei-emails/:id/send # E-Mail senden +POST /api/emails/:id/assign # Vertrag zuordnen +DELETE /api/emails/:id/assign # Zuordnung aufheben +PATCH /api/emails/:id/read # Gelesen/Ungelesen +POST /api/emails/:id/star # Favorit umschalten +DELETE /api/emails/:id # In Papierkorb +POST /api/emails/:id/restore # Aus Papierkorb wiederherstellen +DELETE /api/emails/:id/permanent # Endgültig löschen +GET /api/emails/:id/attachments/:filename # Anhang herunterladen +``` + +#### Datenbank-Modell +```prisma +model CachedEmail { + id Int @id @default(autoincrement()) + stressfreiEmailId Int + stressfreiEmail StressfreiEmail @relation(...) + folder String // INBOX, SENT + messageId String // RFC 5322 Message-ID + uid Int // IMAP UID + subject String? + fromAddress String + fromName String? + toAddresses String @db.Text // JSON Array + ccAddresses String? @db.Text + receivedAt DateTime + textBody String? @db.LongText + htmlBody String? @db.LongText + hasAttachments Boolean @default(false) + attachmentNames String? @db.Text // JSON Array + contractId Int? // Vertragszuordnung + assignedAt DateTime? + assignedBy Int? + isAutoAssigned Boolean @default(false) + isRead Boolean @default(false) + isStarred Boolean @default(false) + isDeleted Boolean @default(false) + deletedAt DateTime? + + @@unique([stressfreiEmailId, messageId, folder]) +} +``` + +#### Sicherheit +- **Passwort-Verschlüsselung**: AES-256-GCM für Mailbox-Passwörter +- **Passwort-Reset**: Neues Passwort generieren und beim Provider setzen +- **Verschlüsselungsmodi**: SSL, STARTTLS, oder unverschlüsselt +- **Selbstsignierte Zertifikate**: Konfigurierbar pro Provider + +#### Berechtigungen +| Aktion | Berechtigung | +|--------|--------------| +| E-Mails lesen | `customers:read` | +| E-Mails senden, markieren | `customers:update` | +| Vertrag zuordnen | `contracts:update` | +| Löschen, Papierkorb | `emails:delete` | + +### Frontend-Komponenten + +| Komponente | Beschreibung | +|------------|--------------| +| `EmailClientTab.tsx` | Haupt-Tab mit Konto-Auswahl und Ordnern | +| `EmailList.tsx` | E-Mail-Liste mit Aktionen | +| `EmailDetail.tsx` | E-Mail-Ansicht mit Anhängen | +| `ComposeEmailModal.tsx` | Neue E-Mail / Antworten | +| `TrashEmailList.tsx` | Papierkorb-Verwaltung | +| `AssignToContractModal.tsx` | Vertragszuordnung | +| `ContractEmailsSection.tsx` | E-Mails in Vertragsansicht | ## Lizenz diff --git a/backend/.gitignore b/backend/.gitignore new file mode 100644 index 00000000..f47e686a --- /dev/null +++ b/backend/.gitignore @@ -0,0 +1,28 @@ +# Dependencies +node_modules/ + +# Build +dist/ + +# Environment +.env +.env.local +.env.*.local + +# Database Backups (can be large, keep folder structure) +prisma/backups/* +!prisma/backups/.gitkeep + +# Logs +*.log +npm-debug.log* + +# IDE +.idea/ +.vscode/ +*.swp +*.swo + +# OS +.DS_Store +Thumbs.db diff --git a/backend/dist/controllers/stressfreiEmail.controller.d.ts b/backend/dist/controllers/stressfreiEmail.controller.d.ts index 5da970e8..83dec1ec 100644 --- a/backend/dist/controllers/stressfreiEmail.controller.d.ts +++ b/backend/dist/controllers/stressfreiEmail.controller.d.ts @@ -4,4 +4,5 @@ export declare function getEmail(req: Request, res: Response): Promise; export declare function createEmail(req: Request, res: Response): Promise; export declare function updateEmail(req: Request, res: Response): Promise; export declare function deleteEmail(req: Request, res: Response): Promise; +export declare function resetPassword(req: Request, res: Response): Promise; //# sourceMappingURL=stressfreiEmail.controller.d.ts.map \ No newline at end of file diff --git a/backend/dist/controllers/stressfreiEmail.controller.d.ts.map b/backend/dist/controllers/stressfreiEmail.controller.d.ts.map index 40ef0a5a..6679bbbe 100644 --- a/backend/dist/controllers/stressfreiEmail.controller.d.ts.map +++ b/backend/dist/controllers/stressfreiEmail.controller.d.ts.map @@ -1 +1 @@ -{"version":3,"file":"stressfreiEmail.controller.d.ts","sourceRoot":"","sources":["../../src/controllers/stressfreiEmail.controller.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,OAAO,EAAE,QAAQ,EAAE,MAAM,SAAS,CAAC;AAI5C,wBAAsB,mBAAmB,CAAC,GAAG,EAAE,OAAO,EAAE,GAAG,EAAE,QAAQ,GAAG,OAAO,CAAC,IAAI,CAAC,CAYpF;AAED,wBAAsB,QAAQ,CAAC,GAAG,EAAE,OAAO,EAAE,GAAG,EAAE,QAAQ,GAAG,OAAO,CAAC,IAAI,CAAC,CAiBzE;AAED,wBAAsB,WAAW,CAAC,GAAG,EAAE,OAAO,EAAE,GAAG,EAAE,QAAQ,GAAG,OAAO,CAAC,IAAI,CAAC,CAc5E;AAED,wBAAsB,WAAW,CAAC,GAAG,EAAE,OAAO,EAAE,GAAG,EAAE,QAAQ,GAAG,OAAO,CAAC,IAAI,CAAC,CAU5E;AAED,wBAAsB,WAAW,CAAC,GAAG,EAAE,OAAO,EAAE,GAAG,EAAE,QAAQ,GAAG,OAAO,CAAC,IAAI,CAAC,CAU5E"} \ No newline at end of file +{"version":3,"file":"stressfreiEmail.controller.d.ts","sourceRoot":"","sources":["../../src/controllers/stressfreiEmail.controller.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,OAAO,EAAE,QAAQ,EAAE,MAAM,SAAS,CAAC;AAI5C,wBAAsB,mBAAmB,CAAC,GAAG,EAAE,OAAO,EAAE,GAAG,EAAE,QAAQ,GAAG,OAAO,CAAC,IAAI,CAAC,CAYpF;AAED,wBAAsB,QAAQ,CAAC,GAAG,EAAE,OAAO,EAAE,GAAG,EAAE,QAAQ,GAAG,OAAO,CAAC,IAAI,CAAC,CAiBzE;AAED,wBAAsB,WAAW,CAAC,GAAG,EAAE,OAAO,EAAE,GAAG,EAAE,QAAQ,GAAG,OAAO,CAAC,IAAI,CAAC,CAc5E;AAED,wBAAsB,WAAW,CAAC,GAAG,EAAE,OAAO,EAAE,GAAG,EAAE,QAAQ,GAAG,OAAO,CAAC,IAAI,CAAC,CAU5E;AAED,wBAAsB,WAAW,CAAC,GAAG,EAAE,OAAO,EAAE,GAAG,EAAE,QAAQ,GAAG,OAAO,CAAC,IAAI,CAAC,CAU5E;AAED,wBAAsB,aAAa,CAAC,GAAG,EAAE,OAAO,EAAE,GAAG,EAAE,QAAQ,GAAG,OAAO,CAAC,IAAI,CAAC,CAqB9E"} \ No newline at end of file diff --git a/backend/dist/controllers/stressfreiEmail.controller.js b/backend/dist/controllers/stressfreiEmail.controller.js index 9fb469df..1dc2e94f 100644 --- a/backend/dist/controllers/stressfreiEmail.controller.js +++ b/backend/dist/controllers/stressfreiEmail.controller.js @@ -38,6 +38,7 @@ exports.getEmail = getEmail; exports.createEmail = createEmail; exports.updateEmail = updateEmail; exports.deleteEmail = deleteEmail; +exports.resetPassword = resetPassword; const stressfreiEmailService = __importStar(require("../services/stressfreiEmail.service.js")); async function getEmailsByCustomer(req, res) { try { @@ -112,4 +113,27 @@ async function deleteEmail(req, res) { }); } } +async function resetPassword(req, res) { + try { + const result = await stressfreiEmailService.resetMailboxPassword(parseInt(req.params.id)); + if (!result.success) { + res.status(400).json({ + success: false, + error: result.error, + }); + return; + } + res.json({ + success: true, + data: { password: result.password }, + message: 'Passwort wurde zurückgesetzt', + }); + } + catch (error) { + res.status(500).json({ + success: false, + error: error instanceof Error ? error.message : 'Fehler beim Zurücksetzen des Passworts', + }); + } +} //# sourceMappingURL=stressfreiEmail.controller.js.map \ No newline at end of file diff --git a/backend/dist/controllers/stressfreiEmail.controller.js.map b/backend/dist/controllers/stressfreiEmail.controller.js.map index 63eec35e..dfeb4afe 100644 --- a/backend/dist/controllers/stressfreiEmail.controller.js.map +++ b/backend/dist/controllers/stressfreiEmail.controller.js.map @@ -1 +1 @@ -{"version":3,"file":"stressfreiEmail.controller.js","sourceRoot":"","sources":["../../src/controllers/stressfreiEmail.controller.ts"],"names":[],"mappings":"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"} \ No newline at end of file +{"version":3,"file":"stressfreiEmail.controller.js","sourceRoot":"","sources":["../../src/controllers/stressfreiEmail.controller.ts"],"names":[],"mappings":"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"} \ No newline at end of file diff --git a/backend/dist/index.js b/backend/dist/index.js index bf410ee0..c5860b79 100644 --- a/backend/dist/index.js +++ b/backend/dist/index.js @@ -27,6 +27,7 @@ const contractCategory_routes_js_1 = __importDefault(require("./routes/contractC const contractTask_routes_js_1 = __importDefault(require("./routes/contractTask.routes.js")); const appSetting_routes_js_1 = __importDefault(require("./routes/appSetting.routes.js")); const emailProvider_routes_js_1 = __importDefault(require("./routes/emailProvider.routes.js")); +const cachedEmail_routes_js_1 = __importDefault(require("./routes/cachedEmail.routes.js")); dotenv_1.default.config(); const app = (0, express_1.default)(); const PORT = process.env.PORT || 3001; @@ -56,6 +57,7 @@ app.use('/api/contract-categories', contractCategory_routes_js_1.default); app.use('/api', contractTask_routes_js_1.default); app.use('/api/settings', appSetting_routes_js_1.default); app.use('/api/email-providers', emailProvider_routes_js_1.default); +app.use('/api', cachedEmail_routes_js_1.default); // Health check app.get('/api/health', (req, res) => { res.json({ status: 'ok', timestamp: new Date().toISOString() }); diff --git a/backend/dist/index.js.map b/backend/dist/index.js.map index 68dc00b7..7cb95a78 100644 --- a/backend/dist/index.js.map +++ b/backend/dist/index.js.map @@ -1 +1 @@ -{"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"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"} \ No newline at end of file +{"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"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"} \ No newline at end of file diff --git a/backend/dist/middleware/auth.d.ts b/backend/dist/middleware/auth.d.ts index 28189a61..fb745a67 100644 --- a/backend/dist/middleware/auth.d.ts +++ b/backend/dist/middleware/auth.d.ts @@ -1,6 +1,6 @@ import { Response, NextFunction } from 'express'; import { AuthRequest } from '../types/index.js'; -export declare function authenticate(req: AuthRequest, res: Response, next: NextFunction): void; +export declare function authenticate(req: AuthRequest, res: Response, next: NextFunction): Promise; export declare function requirePermission(...requiredPermissions: string[]): (req: AuthRequest, res: Response, next: NextFunction) => void; export declare function requireCustomerAccess(req: AuthRequest, res: Response, next: NextFunction): void; //# sourceMappingURL=auth.d.ts.map \ No newline at end of file diff --git a/backend/dist/middleware/auth.d.ts.map b/backend/dist/middleware/auth.d.ts.map index 4175b57f..5a506144 100644 --- a/backend/dist/middleware/auth.d.ts.map +++ b/backend/dist/middleware/auth.d.ts.map @@ -1 +1 @@ -{"version":3,"file":"auth.d.ts","sourceRoot":"","sources":["../../src/middleware/auth.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,QAAQ,EAAE,YAAY,EAAE,MAAM,SAAS,CAAC;AAEjD,OAAO,EAAE,WAAW,EAAc,MAAM,mBAAmB,CAAC;AAE5D,wBAAgB,YAAY,CAC1B,GAAG,EAAE,WAAW,EAChB,GAAG,EAAE,QAAQ,EACb,IAAI,EAAE,YAAY,GACjB,IAAI,CAoBN;AAED,wBAAgB,iBAAiB,CAAC,GAAG,mBAAmB,EAAE,MAAM,EAAE,IACxD,KAAK,WAAW,EAAE,KAAK,QAAQ,EAAE,MAAM,YAAY,KAAG,IAAI,CAuBnE;AAGD,wBAAgB,qBAAqB,CACnC,GAAG,EAAE,WAAW,EAChB,GAAG,EAAE,QAAQ,EACb,IAAI,EAAE,YAAY,GACjB,IAAI,CA4BN"} \ No newline at end of file +{"version":3,"file":"auth.d.ts","sourceRoot":"","sources":["../../src/middleware/auth.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,QAAQ,EAAE,YAAY,EAAE,MAAM,SAAS,CAAC;AAGjD,OAAO,EAAE,WAAW,EAAc,MAAM,mBAAmB,CAAC;AAI5D,wBAAsB,YAAY,CAChC,GAAG,EAAE,WAAW,EAChB,GAAG,EAAE,QAAQ,EACb,IAAI,EAAE,YAAY,GACjB,OAAO,CAAC,IAAI,CAAC,CAuDf;AAED,wBAAgB,iBAAiB,CAAC,GAAG,mBAAmB,EAAE,MAAM,EAAE,IACxD,KAAK,WAAW,EAAE,KAAK,QAAQ,EAAE,MAAM,YAAY,KAAG,IAAI,CAuBnE;AAGD,wBAAgB,qBAAqB,CACnC,GAAG,EAAE,WAAW,EAChB,GAAG,EAAE,QAAQ,EACb,IAAI,EAAE,YAAY,GACjB,IAAI,CA4BN"} \ No newline at end of file diff --git a/backend/dist/middleware/auth.js b/backend/dist/middleware/auth.js index c8b3a32c..04d5739f 100644 --- a/backend/dist/middleware/auth.js +++ b/backend/dist/middleware/auth.js @@ -7,15 +7,48 @@ exports.authenticate = authenticate; exports.requirePermission = requirePermission; exports.requireCustomerAccess = requireCustomerAccess; const jsonwebtoken_1 = __importDefault(require("jsonwebtoken")); -function authenticate(req, res, next) { +const client_1 = require("@prisma/client"); +const prisma = new client_1.PrismaClient(); +async function authenticate(req, res, next) { const authHeader = req.headers.authorization; - if (!authHeader || !authHeader.startsWith('Bearer ')) { + // Token aus Header oder Query-Parameter (für Downloads) + let token = null; + if (authHeader && authHeader.startsWith('Bearer ')) { + token = authHeader.split(' ')[1]; + } + else if (req.query.token && typeof req.query.token === 'string') { + // Fallback für Downloads: Token als Query-Parameter + token = req.query.token; + } + if (!token) { res.status(401).json({ success: false, error: 'Nicht authentifiziert' }); return; } - const token = authHeader.split(' ')[1]; try { const decoded = jsonwebtoken_1.default.verify(token, process.env.JWT_SECRET || 'fallback-secret'); + // Prüfen ob Token durch Rechteänderung invalidiert wurde (nur für Mitarbeiter) + if (decoded.userId && decoded.iat) { + const user = await prisma.user.findUnique({ + where: { id: decoded.userId }, + select: { tokenInvalidatedAt: true, isActive: true }, + }); + // Benutzer nicht gefunden oder deaktiviert + if (!user || !user.isActive) { + res.status(401).json({ success: false, error: 'Benutzer nicht mehr aktiv' }); + return; + } + // Token wurde vor der Invalidierung ausgestellt + if (user.tokenInvalidatedAt) { + const tokenIssuedAt = decoded.iat * 1000; // iat ist in Sekunden, Date ist in Millisekunden + if (tokenIssuedAt < user.tokenInvalidatedAt.getTime()) { + res.status(401).json({ + success: false, + error: 'Ihre Berechtigungen wurden geändert. Bitte melden Sie sich erneut an.', + }); + return; + } + } + } req.user = decoded; next(); } diff --git a/backend/dist/middleware/auth.js.map b/backend/dist/middleware/auth.js.map index cf6fecc7..b4058a31 100644 --- a/backend/dist/middleware/auth.js.map +++ b/backend/dist/middleware/auth.js.map @@ -1 +1 @@ -{"version":3,"file":"auth.js","sourceRoot":"","sources":["../../src/middleware/auth.ts"],"names":[],"mappings":"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"} \ No newline at end of file +{"version":3,"file":"auth.js","sourceRoot":"","sources":["../../src/middleware/auth.ts"],"names":[],"mappings":"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"} \ No newline at end of file diff --git a/backend/dist/routes/appSetting.routes.d.ts.map b/backend/dist/routes/appSetting.routes.d.ts.map index 0ce58633..7eac622f 100644 --- a/backend/dist/routes/appSetting.routes.d.ts.map +++ b/backend/dist/routes/appSetting.routes.d.ts.map @@ -1 +1 @@ -{"version":3,"file":"appSetting.routes.d.ts","sourceRoot":"","sources":["../../src/routes/appSetting.routes.ts"],"names":[],"mappings":"AAIA,QAAA,MAAM,MAAM,4CAAW,CAAC;AAwBxB,eAAe,MAAM,CAAC"} \ No newline at end of file +{"version":3,"file":"appSetting.routes.d.ts","sourceRoot":"","sources":["../../src/routes/appSetting.routes.ts"],"names":[],"mappings":"AAmBA,QAAA,MAAM,MAAM,4CAAW,CAAC;AAmFxB,eAAe,MAAM,CAAC"} \ No newline at end of file diff --git a/backend/dist/routes/appSetting.routes.js b/backend/dist/routes/appSetting.routes.js index e69a5e15..c0a6a640 100644 --- a/backend/dist/routes/appSetting.routes.js +++ b/backend/dist/routes/appSetting.routes.js @@ -32,10 +32,28 @@ var __importStar = (this && this.__importStar) || (function () { return result; }; })(); +var __importDefault = (this && this.__importDefault) || function (mod) { + return (mod && mod.__esModule) ? mod : { "default": mod }; +}; Object.defineProperty(exports, "__esModule", { value: true }); const express_1 = require("express"); +const multer_1 = __importDefault(require("multer")); const appSettingController = __importStar(require("../controllers/appSetting.controller.js")); +const backupController = __importStar(require("../controllers/backup.controller.js")); const auth_js_1 = require("../middleware/auth.js"); +// Multer für Backup-Upload (in Memory speichern) +const backupUpload = (0, multer_1.default)({ + storage: multer_1.default.memoryStorage(), + limits: { fileSize: 500 * 1024 * 1024 }, // 500MB max + fileFilter: (req, file, cb) => { + if (file.mimetype === 'application/zip' || file.originalname.endsWith('.zip')) { + cb(null, true); + } + else { + cb(new Error('Nur ZIP-Dateien sind erlaubt')); + } + }, +}); const router = (0, express_1.Router)(); // Öffentliche Einstellungen (für alle authentifizierten Benutzer, inkl. Kunden) router.get('/public', auth_js_1.authenticate, appSettingController.getPublicSettings); @@ -45,5 +63,20 @@ router.get('/', auth_js_1.authenticate, (0, auth_js_1.requirePermission)('settin router.put('/:key', auth_js_1.authenticate, (0, auth_js_1.requirePermission)('settings:update'), appSettingController.updateSetting); // Mehrere Einstellungen aktualisieren (nur Admin) router.put('/', auth_js_1.authenticate, (0, auth_js_1.requirePermission)('settings:update'), appSettingController.updateSettings); +// ==================== BACKUP & RESTORE ==================== +// Liste aller Backups +router.get('/backups', auth_js_1.authenticate, (0, auth_js_1.requirePermission)('settings:update'), backupController.listBackups); +// Neues Backup erstellen +router.post('/backup', auth_js_1.authenticate, (0, auth_js_1.requirePermission)('settings:update'), backupController.createBackup); +// Backup wiederherstellen +router.post('/backup/:name/restore', auth_js_1.authenticate, (0, auth_js_1.requirePermission)('settings:update'), backupController.restoreBackup); +// Backup löschen +router.delete('/backup/:name', auth_js_1.authenticate, (0, auth_js_1.requirePermission)('settings:update'), backupController.deleteBackup); +// Backup als ZIP herunterladen +router.get('/backup/:name/download', auth_js_1.authenticate, (0, auth_js_1.requirePermission)('settings:update'), backupController.downloadBackup); +// Backup-ZIP hochladen +router.post('/backup/upload', auth_js_1.authenticate, (0, auth_js_1.requirePermission)('settings:update'), backupUpload.single('backup'), backupController.uploadBackup); +// Werkseinstellungen (alles löschen) +router.post('/factory-reset', auth_js_1.authenticate, (0, auth_js_1.requirePermission)('settings:update'), backupController.factoryReset); exports.default = router; //# sourceMappingURL=appSetting.routes.js.map \ No newline at end of file diff --git a/backend/dist/routes/appSetting.routes.js.map b/backend/dist/routes/appSetting.routes.js.map index 94013a18..4b10f4ba 100644 --- a/backend/dist/routes/appSetting.routes.js.map +++ b/backend/dist/routes/appSetting.routes.js.map @@ -1 +1 @@ -{"version":3,"file":"appSetting.routes.js","sourceRoot":"","sources":["../../src/routes/appSetting.routes.ts"],"names":[],"mappings":";;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;AAAA,qCAAiC;AACjC,8FAAgF;AAChF,mDAAwE;AAExE,MAAM,MAAM,GAAG,IAAA,gBAAM,GAAE,CAAC;AAExB,gFAAgF;AAChF,MAAM,CAAC,GAAG,CAAC,SAAS,EAAE,sBAAY,EAAE,oBAAoB,CAAC,iBAAiB,CAAC,CAAC;AAE5E,iCAAiC;AACjC,MAAM,CAAC,GAAG,CAAC,GAAG,EAAE,sBAAY,EAAE,IAAA,2BAAiB,EAAC,eAAe,CAAC,EAAE,oBAAoB,CAAC,cAAc,CAAC,CAAC;AAEvG,iDAAiD;AACjD,MAAM,CAAC,GAAG,CACR,OAAO,EACP,sBAAY,EACZ,IAAA,2BAAiB,EAAC,iBAAiB,CAAC,EACpC,oBAAoB,CAAC,aAAa,CACnC,CAAC;AAEF,kDAAkD;AAClD,MAAM,CAAC,GAAG,CACR,GAAG,EACH,sBAAY,EACZ,IAAA,2BAAiB,EAAC,iBAAiB,CAAC,EACpC,oBAAoB,CAAC,cAAc,CACpC,CAAC;AAEF,kBAAe,MAAM,CAAC"} \ No newline at end of file +{"version":3,"file":"appSetting.routes.js","sourceRoot":"","sources":["../../src/routes/appSetting.routes.ts"],"names":[],"mappings":";;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;AAAA,qCAAiC;AACjC,oDAA4B;AAC5B,8FAAgF;AAChF,sFAAwE;AACxE,mDAAwE;AAExE,iDAAiD;AACjD,MAAM,YAAY,GAAG,IAAA,gBAAM,EAAC;IAC1B,OAAO,EAAE,gBAAM,CAAC,aAAa,EAAE;IAC/B,MAAM,EAAE,EAAE,QAAQ,EAAE,GAAG,GAAG,IAAI,GAAG,IAAI,EAAE,EAAE,YAAY;IACrD,UAAU,EAAE,CAAC,GAAG,EAAE,IAAI,EAAE,EAAE,EAAE,EAAE;QAC5B,IAAI,IAAI,CAAC,QAAQ,KAAK,iBAAiB,IAAI,IAAI,CAAC,YAAY,CAAC,QAAQ,CAAC,MAAM,CAAC,EAAE,CAAC;YAC9E,EAAE,CAAC,IAAI,EAAE,IAAI,CAAC,CAAC;QACjB,CAAC;aAAM,CAAC;YACN,EAAE,CAAC,IAAI,KAAK,CAAC,8BAA8B,CAAC,CAAC,CAAC;QAChD,CAAC;IACH,CAAC;CACF,CAAC,CAAC;AAEH,MAAM,MAAM,GAAG,IAAA,gBAAM,GAAE,CAAC;AAExB,gFAAgF;AAChF,MAAM,CAAC,GAAG,CAAC,SAAS,EAAE,sBAAY,EAAE,oBAAoB,CAAC,iBAAiB,CAAC,CAAC;AAE5E,iCAAiC;AACjC,MAAM,CAAC,GAAG,CAAC,GAAG,EAAE,sBAAY,EAAE,IAAA,2BAAiB,EAAC,eAAe,CAAC,EAAE,oBAAoB,CAAC,cAAc,CAAC,CAAC;AAEvG,iDAAiD;AACjD,MAAM,CAAC,GAAG,CACR,OAAO,EACP,sBAAY,EACZ,IAAA,2BAAiB,EAAC,iBAAiB,CAAC,EACpC,oBAAoB,CAAC,aAAa,CACnC,CAAC;AAEF,kDAAkD;AAClD,MAAM,CAAC,GAAG,CACR,GAAG,EACH,sBAAY,EACZ,IAAA,2BAAiB,EAAC,iBAAiB,CAAC,EACpC,oBAAoB,CAAC,cAAc,CACpC,CAAC;AAEF,6DAA6D;AAE7D,sBAAsB;AACtB,MAAM,CAAC,GAAG,CACR,UAAU,EACV,sBAAY,EACZ,IAAA,2BAAiB,EAAC,iBAAiB,CAAC,EACpC,gBAAgB,CAAC,WAAW,CAC7B,CAAC;AAEF,yBAAyB;AACzB,MAAM,CAAC,IAAI,CACT,SAAS,EACT,sBAAY,EACZ,IAAA,2BAAiB,EAAC,iBAAiB,CAAC,EACpC,gBAAgB,CAAC,YAAY,CAC9B,CAAC;AAEF,0BAA0B;AAC1B,MAAM,CAAC,IAAI,CACT,uBAAuB,EACvB,sBAAY,EACZ,IAAA,2BAAiB,EAAC,iBAAiB,CAAC,EACpC,gBAAgB,CAAC,aAAa,CAC/B,CAAC;AAEF,iBAAiB;AACjB,MAAM,CAAC,MAAM,CACX,eAAe,EACf,sBAAY,EACZ,IAAA,2BAAiB,EAAC,iBAAiB,CAAC,EACpC,gBAAgB,CAAC,YAAY,CAC9B,CAAC;AAEF,+BAA+B;AAC/B,MAAM,CAAC,GAAG,CACR,wBAAwB,EACxB,sBAAY,EACZ,IAAA,2BAAiB,EAAC,iBAAiB,CAAC,EACpC,gBAAgB,CAAC,cAAc,CAChC,CAAC;AAEF,uBAAuB;AACvB,MAAM,CAAC,IAAI,CACT,gBAAgB,EAChB,sBAAY,EACZ,IAAA,2BAAiB,EAAC,iBAAiB,CAAC,EACpC,YAAY,CAAC,MAAM,CAAC,QAAQ,CAAC,EAC7B,gBAAgB,CAAC,YAAY,CAC9B,CAAC;AAEF,qCAAqC;AACrC,MAAM,CAAC,IAAI,CACT,gBAAgB,EAChB,sBAAY,EACZ,IAAA,2BAAiB,EAAC,iBAAiB,CAAC,EACpC,gBAAgB,CAAC,YAAY,CAC9B,CAAC;AAEF,kBAAe,MAAM,CAAC"} \ No newline at end of file diff --git a/backend/dist/routes/contractCategory.routes.d.ts.map b/backend/dist/routes/contractCategory.routes.d.ts.map index a088bc71..db522560 100644 --- a/backend/dist/routes/contractCategory.routes.d.ts.map +++ b/backend/dist/routes/contractCategory.routes.d.ts.map @@ -1 +1 @@ -{"version":3,"file":"contractCategory.routes.d.ts","sourceRoot":"","sources":["../../src/routes/contractCategory.routes.ts"],"names":[],"mappings":"AAIA,QAAA,MAAM,MAAM,4CAAW,CAAC;AAQxB,eAAe,MAAM,CAAC"} \ No newline at end of file +{"version":3,"file":"contractCategory.routes.d.ts","sourceRoot":"","sources":["../../src/routes/contractCategory.routes.ts"],"names":[],"mappings":"AAIA,QAAA,MAAM,MAAM,4CAAW,CAAC;AAWxB,eAAe,MAAM,CAAC"} \ No newline at end of file diff --git a/backend/dist/routes/contractCategory.routes.js b/backend/dist/routes/contractCategory.routes.js index 490b6575..35f9274b 100644 --- a/backend/dist/routes/contractCategory.routes.js +++ b/backend/dist/routes/contractCategory.routes.js @@ -37,10 +37,12 @@ const express_1 = require("express"); const contractCategoryController = __importStar(require("../controllers/contractCategory.controller.js")); const auth_js_1 = require("../middleware/auth.js"); const router = (0, express_1.Router)(); +// Lesen für alle authentifizierten Benutzer router.get('/', auth_js_1.authenticate, contractCategoryController.getContractCategories); -router.post('/', auth_js_1.authenticate, (0, auth_js_1.requirePermission)('platforms:create'), contractCategoryController.createContractCategory); router.get('/:id', auth_js_1.authenticate, contractCategoryController.getContractCategory); -router.put('/:id', auth_js_1.authenticate, (0, auth_js_1.requirePermission)('platforms:update'), contractCategoryController.updateContractCategory); -router.delete('/:id', auth_js_1.authenticate, (0, auth_js_1.requirePermission)('platforms:delete'), contractCategoryController.deleteContractCategory); +// Ändern/Löschen nur mit Entwickler-Berechtigung (Vertragstypen erfordern Formular-Anpassungen) +router.post('/', auth_js_1.authenticate, (0, auth_js_1.requirePermission)('developer:access'), contractCategoryController.createContractCategory); +router.put('/:id', auth_js_1.authenticate, (0, auth_js_1.requirePermission)('developer:access'), contractCategoryController.updateContractCategory); +router.delete('/:id', auth_js_1.authenticate, (0, auth_js_1.requirePermission)('developer:access'), contractCategoryController.deleteContractCategory); exports.default = router; //# sourceMappingURL=contractCategory.routes.js.map \ No newline at end of file diff --git a/backend/dist/routes/contractCategory.routes.js.map b/backend/dist/routes/contractCategory.routes.js.map index 0bb5c22b..b738ce8c 100644 --- a/backend/dist/routes/contractCategory.routes.js.map +++ b/backend/dist/routes/contractCategory.routes.js.map @@ -1 +1 @@ -{"version":3,"file":"contractCategory.routes.js","sourceRoot":"","sources":["../../src/routes/contractCategory.routes.ts"],"names":[],"mappings":";;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;AAAA,qCAAiC;AACjC,0GAA4F;AAC5F,mDAAwE;AAExE,MAAM,MAAM,GAAG,IAAA,gBAAM,GAAE,CAAC;AAExB,MAAM,CAAC,GAAG,CAAC,GAAG,EAAE,sBAAY,EAAE,0BAA0B,CAAC,qBAAqB,CAAC,CAAC;AAChF,MAAM,CAAC,IAAI,CAAC,GAAG,EAAE,sBAAY,EAAE,IAAA,2BAAiB,EAAC,kBAAkB,CAAC,EAAE,0BAA0B,CAAC,sBAAsB,CAAC,CAAC;AACzH,MAAM,CAAC,GAAG,CAAC,MAAM,EAAE,sBAAY,EAAE,0BAA0B,CAAC,mBAAmB,CAAC,CAAC;AACjF,MAAM,CAAC,GAAG,CAAC,MAAM,EAAE,sBAAY,EAAE,IAAA,2BAAiB,EAAC,kBAAkB,CAAC,EAAE,0BAA0B,CAAC,sBAAsB,CAAC,CAAC;AAC3H,MAAM,CAAC,MAAM,CAAC,MAAM,EAAE,sBAAY,EAAE,IAAA,2BAAiB,EAAC,kBAAkB,CAAC,EAAE,0BAA0B,CAAC,sBAAsB,CAAC,CAAC;AAE9H,kBAAe,MAAM,CAAC"} \ No newline at end of file +{"version":3,"file":"contractCategory.routes.js","sourceRoot":"","sources":["../../src/routes/contractCategory.routes.ts"],"names":[],"mappings":";;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;AAAA,qCAAiC;AACjC,0GAA4F;AAC5F,mDAAwE;AAExE,MAAM,MAAM,GAAG,IAAA,gBAAM,GAAE,CAAC;AAExB,4CAA4C;AAC5C,MAAM,CAAC,GAAG,CAAC,GAAG,EAAE,sBAAY,EAAE,0BAA0B,CAAC,qBAAqB,CAAC,CAAC;AAChF,MAAM,CAAC,GAAG,CAAC,MAAM,EAAE,sBAAY,EAAE,0BAA0B,CAAC,mBAAmB,CAAC,CAAC;AAEjF,gGAAgG;AAChG,MAAM,CAAC,IAAI,CAAC,GAAG,EAAE,sBAAY,EAAE,IAAA,2BAAiB,EAAC,kBAAkB,CAAC,EAAE,0BAA0B,CAAC,sBAAsB,CAAC,CAAC;AACzH,MAAM,CAAC,GAAG,CAAC,MAAM,EAAE,sBAAY,EAAE,IAAA,2BAAiB,EAAC,kBAAkB,CAAC,EAAE,0BAA0B,CAAC,sBAAsB,CAAC,CAAC;AAC3H,MAAM,CAAC,MAAM,CAAC,MAAM,EAAE,sBAAY,EAAE,IAAA,2BAAiB,EAAC,kBAAkB,CAAC,EAAE,0BAA0B,CAAC,sBAAsB,CAAC,CAAC;AAE9H,kBAAe,MAAM,CAAC"} \ No newline at end of file diff --git a/backend/dist/routes/stressfreiEmail.routes.d.ts.map b/backend/dist/routes/stressfreiEmail.routes.d.ts.map index 12a5fb47..b02385f0 100644 --- a/backend/dist/routes/stressfreiEmail.routes.d.ts.map +++ b/backend/dist/routes/stressfreiEmail.routes.d.ts.map @@ -1 +1 @@ -{"version":3,"file":"stressfreiEmail.routes.d.ts","sourceRoot":"","sources":["../../src/routes/stressfreiEmail.routes.ts"],"names":[],"mappings":"AAIA,QAAA,MAAM,MAAM,4CAAW,CAAC;AAOxB,eAAe,MAAM,CAAC"} \ No newline at end of file +{"version":3,"file":"stressfreiEmail.routes.d.ts","sourceRoot":"","sources":["../../src/routes/stressfreiEmail.routes.ts"],"names":[],"mappings":"AAIA,QAAA,MAAM,MAAM,4CAAW,CAAC;AAUxB,eAAe,MAAM,CAAC"} \ No newline at end of file diff --git a/backend/dist/routes/stressfreiEmail.routes.js b/backend/dist/routes/stressfreiEmail.routes.js index 76e3b072..33d43094 100644 --- a/backend/dist/routes/stressfreiEmail.routes.js +++ b/backend/dist/routes/stressfreiEmail.routes.js @@ -41,5 +41,7 @@ const router = (0, express_1.Router)(); router.get('/:id', auth_js_1.authenticate, (0, auth_js_1.requirePermission)('customers:read'), stressfreiEmailController.getEmail); router.put('/:id', auth_js_1.authenticate, (0, auth_js_1.requirePermission)('customers:update'), stressfreiEmailController.updateEmail); router.delete('/:id', auth_js_1.authenticate, (0, auth_js_1.requirePermission)('customers:delete'), stressfreiEmailController.deleteEmail); +// Passwort zurücksetzen (generiert neues Passwort und setzt es beim Provider) +router.post('/:id/reset-password', auth_js_1.authenticate, (0, auth_js_1.requirePermission)('customers:update'), stressfreiEmailController.resetPassword); exports.default = router; //# sourceMappingURL=stressfreiEmail.routes.js.map \ No newline at end of file diff --git a/backend/dist/routes/stressfreiEmail.routes.js.map b/backend/dist/routes/stressfreiEmail.routes.js.map index 64b2fe8d..2693b11c 100644 --- a/backend/dist/routes/stressfreiEmail.routes.js.map +++ b/backend/dist/routes/stressfreiEmail.routes.js.map @@ -1 +1 @@ -{"version":3,"file":"stressfreiEmail.routes.js","sourceRoot":"","sources":["../../src/routes/stressfreiEmail.routes.ts"],"names":[],"mappings":";;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;AAAA,qCAAiC;AACjC,wGAA0F;AAC1F,mDAAwE;AAExE,MAAM,MAAM,GAAG,IAAA,gBAAM,GAAE,CAAC;AAExB,sCAAsC;AACtC,MAAM,CAAC,GAAG,CAAC,MAAM,EAAE,sBAAY,EAAE,IAAA,2BAAiB,EAAC,gBAAgB,CAAC,EAAE,yBAAyB,CAAC,QAAQ,CAAC,CAAC;AAC1G,MAAM,CAAC,GAAG,CAAC,MAAM,EAAE,sBAAY,EAAE,IAAA,2BAAiB,EAAC,kBAAkB,CAAC,EAAE,yBAAyB,CAAC,WAAW,CAAC,CAAC;AAC/G,MAAM,CAAC,MAAM,CAAC,MAAM,EAAE,sBAAY,EAAE,IAAA,2BAAiB,EAAC,kBAAkB,CAAC,EAAE,yBAAyB,CAAC,WAAW,CAAC,CAAC;AAElH,kBAAe,MAAM,CAAC"} \ No newline at end of file +{"version":3,"file":"stressfreiEmail.routes.js","sourceRoot":"","sources":["../../src/routes/stressfreiEmail.routes.ts"],"names":[],"mappings":";;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;AAAA,qCAAiC;AACjC,wGAA0F;AAC1F,mDAAwE;AAExE,MAAM,MAAM,GAAG,IAAA,gBAAM,GAAE,CAAC;AAExB,sCAAsC;AACtC,MAAM,CAAC,GAAG,CAAC,MAAM,EAAE,sBAAY,EAAE,IAAA,2BAAiB,EAAC,gBAAgB,CAAC,EAAE,yBAAyB,CAAC,QAAQ,CAAC,CAAC;AAC1G,MAAM,CAAC,GAAG,CAAC,MAAM,EAAE,sBAAY,EAAE,IAAA,2BAAiB,EAAC,kBAAkB,CAAC,EAAE,yBAAyB,CAAC,WAAW,CAAC,CAAC;AAC/G,MAAM,CAAC,MAAM,CAAC,MAAM,EAAE,sBAAY,EAAE,IAAA,2BAAiB,EAAC,kBAAkB,CAAC,EAAE,yBAAyB,CAAC,WAAW,CAAC,CAAC;AAElH,8EAA8E;AAC9E,MAAM,CAAC,IAAI,CAAC,qBAAqB,EAAE,sBAAY,EAAE,IAAA,2BAAiB,EAAC,kBAAkB,CAAC,EAAE,yBAAyB,CAAC,aAAa,CAAC,CAAC;AAEjI,kBAAe,MAAM,CAAC"} \ No newline at end of file diff --git a/backend/dist/services/contract.service.d.ts b/backend/dist/services/contract.service.d.ts index ebc7f350..778e7c86 100644 --- a/backend/dist/services/contract.service.d.ts +++ b/backend/dist/services/contract.service.d.ts @@ -247,10 +247,12 @@ export declare function getContractById(id: number, decryptPassword?: boolean): createdAt: Date; updatedAt: Date; notes: string | null; + hasMailbox: boolean; platform: string | null; isProvisioned: boolean; provisionedAt: Date | null; provisionError: string | null; + emailPasswordEncrypted: string | null; } | null; carInsuranceDetails: { id: number; @@ -511,6 +513,11 @@ export declare function getContractById(id: number, decryptPassword?: boolean): portalUsername: string | null; stressfreiEmailId: number | null; }) | null; + followUpContract: { + id: number; + status: import(".prisma/client").$Enums.ContractStatus; + contractNumber: string; + } | null; } & { id: number; customerId: number; @@ -936,10 +943,12 @@ export declare function updateContract(id: number, data: Partial; export declare function getProviderConfigById(id: number): Promise<{ id: number; @@ -28,6 +35,13 @@ export declare function getProviderConfigById(id: number): Promise<{ passwordEncrypted: string | null; domain: string; defaultForwardEmail: string | null; + imapServer: string | null; + imapPort: number | null; + smtpServer: string | null; + smtpPort: number | null; + imapEncryption: import(".prisma/client").$Enums.MailEncryption; + smtpEncryption: import(".prisma/client").$Enums.MailEncryption; + allowSelfSignedCerts: boolean; } | null>; export declare function getDefaultProviderConfig(): Promise<{ id: number; @@ -43,6 +57,13 @@ export declare function getDefaultProviderConfig(): Promise<{ passwordEncrypted: string | null; domain: string; defaultForwardEmail: string | null; + imapServer: string | null; + imapPort: number | null; + smtpServer: string | null; + smtpPort: number | null; + imapEncryption: import(".prisma/client").$Enums.MailEncryption; + smtpEncryption: import(".prisma/client").$Enums.MailEncryption; + allowSelfSignedCerts: boolean; } | null>; export declare function getActiveProviderConfig(): Promise<{ id: number; @@ -58,6 +79,13 @@ export declare function getActiveProviderConfig(): Promise<{ passwordEncrypted: string | null; domain: string; defaultForwardEmail: string | null; + imapServer: string | null; + imapPort: number | null; + smtpServer: string | null; + smtpPort: number | null; + imapEncryption: import(".prisma/client").$Enums.MailEncryption; + smtpEncryption: import(".prisma/client").$Enums.MailEncryption; + allowSelfSignedCerts: boolean; } | null>; export interface CreateProviderConfigData { name: string; @@ -68,6 +96,9 @@ export interface CreateProviderConfigData { password?: string; domain: string; defaultForwardEmail?: string; + imapEncryption?: MailEncryption; + smtpEncryption?: MailEncryption; + allowSelfSignedCerts?: boolean; isActive?: boolean; isDefault?: boolean; } @@ -85,6 +116,13 @@ export declare function createProviderConfig(data: CreateProviderConfigData): Pr passwordEncrypted: string | null; domain: string; defaultForwardEmail: string | null; + imapServer: string | null; + imapPort: number | null; + smtpServer: string | null; + smtpPort: number | null; + imapEncryption: import(".prisma/client").$Enums.MailEncryption; + smtpEncryption: import(".prisma/client").$Enums.MailEncryption; + allowSelfSignedCerts: boolean; }>; export declare function updateProviderConfig(id: number, data: Partial): Promise<{ id: number; @@ -100,6 +138,13 @@ export declare function updateProviderConfig(id: number, data: Partial; export declare function deleteProviderConfig(id: number): Promise<{ id: number; @@ -115,9 +160,32 @@ export declare function deleteProviderConfig(id: number): Promise<{ passwordEncrypted: string | null; domain: string; defaultForwardEmail: string | null; + imapServer: string | null; + imapPort: number | null; + smtpServer: string | null; + smtpPort: number | null; + imapEncryption: import(".prisma/client").$Enums.MailEncryption; + smtpEncryption: import(".prisma/client").$Enums.MailEncryption; + allowSelfSignedCerts: boolean; }>; export declare function checkEmailExists(localPart: string): Promise; export declare function provisionEmail(localPart: string, customerEmail: string): Promise; +export declare function provisionEmailWithMailbox(localPart: string, customerEmail: string, password: string): Promise; +export declare function enableMailboxForExistingEmail(localPart: string, password: string): Promise; +export declare function updateMailboxPassword(localPart: string, password: string): Promise; +export interface ImapSmtpSettings { + imapServer: string; + imapPort: number; + imapEncryption: MailEncryption; + smtpServer: string; + smtpPort: number; + smtpEncryption: MailEncryption; + allowSelfSignedCerts: boolean; + domain: string; +} +export declare function getImapSmtpSettings(): Promise; export declare function deprovisionEmail(localPart: string): Promise; export declare function renameProvisionedEmail(oldLocalPart: string, newLocalPart: string): Promise; export declare function getProviderDomain(): Promise; diff --git a/backend/dist/services/emailProvider/emailProviderService.d.ts.map b/backend/dist/services/emailProvider/emailProviderService.d.ts.map index 2ef1994f..8163bbe3 100644 --- a/backend/dist/services/emailProvider/emailProviderService.d.ts.map +++ b/backend/dist/services/emailProvider/emailProviderService.d.ts.map @@ -1 +1 @@ -{"version":3,"file":"emailProviderService.d.ts","sourceRoot":"","sources":["../../../src/services/emailProvider/emailProviderService.ts"],"names":[],"mappings":"AAIA,OAAO,EAGL,iBAAiB,EACjB,oBAAoB,EAErB,MAAM,YAAY,CAAC;AAuBpB,wBAAsB,qBAAqB;;;;;;;;;;;;;;KAI1C;AAED,wBAAsB,qBAAqB,CAAC,EAAE,EAAE,MAAM;;;;;;;;;;;;;;UAIrD;AAED,wBAAsB,wBAAwB;;;;;;;;;;;;;;UAI7C;AAED,wBAAsB,uBAAuB;;;;;;;;;;;;;;UAQ5C;AAED,MAAM,WAAW,wBAAwB;IACvC,IAAI,EAAE,MAAM,CAAC;IACb,IAAI,EAAE,OAAO,GAAG,QAAQ,GAAG,aAAa,CAAC;IACzC,MAAM,EAAE,MAAM,CAAC;IACf,MAAM,CAAC,EAAE,MAAM,CAAC;IAChB,QAAQ,CAAC,EAAE,MAAM,CAAC;IAClB,QAAQ,CAAC,EAAE,MAAM,CAAC;IAClB,MAAM,EAAE,MAAM,CAAC;IACf,mBAAmB,CAAC,EAAE,MAAM,CAAC;IAC7B,QAAQ,CAAC,EAAE,OAAO,CAAC;IACnB,SAAS,CAAC,EAAE,OAAO,CAAC;CACrB;AAED,wBAAsB,oBAAoB,CAAC,IAAI,EAAE,wBAAwB;;;;;;;;;;;;;;GA2BxE;AAED,wBAAsB,oBAAoB,CACxC,EAAE,EAAE,MAAM,EACV,IAAI,EAAE,OAAO,CAAC,wBAAwB,CAAC;;;;;;;;;;;;;;GAsCxC;AAED,wBAAsB,oBAAoB,CAAC,EAAE,EAAE,MAAM;;;;;;;;;;;;;;GAIpD;AAwCD,wBAAsB,gBAAgB,CAAC,SAAS,EAAE,MAAM,GAAG,OAAO,CAAC,iBAAiB,CAAC,CAQpF;AAGD,wBAAsB,cAAc,CAClC,SAAS,EAAE,MAAM,EACjB,aAAa,EAAE,MAAM,GACpB,OAAO,CAAC,oBAAoB,CAAC,CAoC/B;AAGD,wBAAsB,gBAAgB,CAAC,SAAS,EAAE,MAAM,GAAG,OAAO,CAAC,oBAAoB,CAAC,CAWvF;AAGD,wBAAsB,sBAAsB,CAC1C,YAAY,EAAE,MAAM,EACpB,YAAY,EAAE,MAAM,GACnB,OAAO,CAAC,oBAAoB,CAAC,CAW/B;AAGD,wBAAsB,iBAAiB,IAAI,OAAO,CAAC,MAAM,GAAG,IAAI,CAAC,CAGhE;AA8DD,wBAAsB,sBAAsB,CAAC,OAAO,CAAC,EAAE;IACrD,EAAE,CAAC,EAAE,MAAM,CAAC;IACZ,QAAQ,CAAC,EAAE;QACT,IAAI,EAAE,OAAO,GAAG,QAAQ,GAAG,aAAa,CAAC;QACzC,MAAM,EAAE,MAAM,CAAC;QACf,MAAM,CAAC,EAAE,MAAM,CAAC;QAChB,QAAQ,CAAC,EAAE,MAAM,CAAC;QAClB,QAAQ,CAAC,EAAE,MAAM,CAAC;QAClB,MAAM,EAAE,MAAM,CAAC;KAChB,CAAC;CACH,GAAG,OAAO,CAAC,oBAAoB,CAAC,CA6BhC"} \ No newline at end of file +{"version":3,"file":"emailProviderService.d.ts","sourceRoot":"","sources":["../../../src/services/emailProvider/emailProviderService.ts"],"names":[],"mappings":"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"} \ No newline at end of file diff --git a/backend/dist/services/emailProvider/emailProviderService.js b/backend/dist/services/emailProvider/emailProviderService.js index 8c9138df..91c46ad0 100644 --- a/backend/dist/services/emailProvider/emailProviderService.js +++ b/backend/dist/services/emailProvider/emailProviderService.js @@ -10,6 +10,10 @@ exports.updateProviderConfig = updateProviderConfig; exports.deleteProviderConfig = deleteProviderConfig; exports.checkEmailExists = checkEmailExists; exports.provisionEmail = provisionEmail; +exports.provisionEmailWithMailbox = provisionEmailWithMailbox; +exports.enableMailboxForExistingEmail = enableMailboxForExistingEmail; +exports.updateMailboxPassword = updateMailboxPassword; +exports.getImapSmtpSettings = getImapSmtpSettings; exports.deprovisionEmail = deprovisionEmail; exports.renameProvisionedEmail = renameProvisionedEmail; exports.getProviderDomain = getProviderDomain; @@ -79,6 +83,9 @@ async function createProviderConfig(data) { passwordEncrypted, domain: data.domain, defaultForwardEmail: data.defaultForwardEmail || null, + imapEncryption: data.imapEncryption ?? 'SSL', + smtpEncryption: data.smtpEncryption ?? 'SSL', + allowSelfSignedCerts: data.allowSelfSignedCerts ?? false, isActive: data.isActive ?? true, isDefault: data.isDefault ?? false, }, @@ -107,6 +114,12 @@ async function updateProviderConfig(id, data) { updateData.domain = data.domain; if (data.defaultForwardEmail !== undefined) updateData.defaultForwardEmail = data.defaultForwardEmail || null; + if (data.imapEncryption !== undefined) + updateData.imapEncryption = data.imapEncryption; + if (data.smtpEncryption !== undefined) + updateData.smtpEncryption = data.smtpEncryption; + if (data.allowSelfSignedCerts !== undefined) + updateData.allowSelfSignedCerts = data.allowSelfSignedCerts; if (data.isActive !== undefined) updateData.isActive = data.isActive; if (data.isDefault !== undefined) @@ -159,6 +172,13 @@ async function getProviderInstance() { password, domain: dbConfig.domain, defaultForwardEmail: dbConfig.defaultForwardEmail || undefined, + imapServer: dbConfig.imapServer || undefined, + imapPort: dbConfig.imapPort || undefined, + smtpServer: dbConfig.smtpServer || undefined, + smtpPort: dbConfig.smtpPort || undefined, + imapEncryption: dbConfig.imapEncryption, + smtpEncryption: dbConfig.smtpEncryption, + allowSelfSignedCerts: dbConfig.allowSelfSignedCerts, isActive: dbConfig.isActive, isDefault: dbConfig.isDefault, }; @@ -209,6 +229,136 @@ async function provisionEmail(localPart, customerEmail) { }; } } +// E-Mail mit echter Mailbox erstellen (IMAP/SMTP-Zugang) +async function provisionEmailWithMailbox(localPart, customerEmail, password) { + try { + const provider = await getProviderInstance(); + const config = await getActiveProviderConfig(); + // Weiterleitungsziele zusammenstellen + const forwardTargets = [customerEmail]; + // Unsere eigene Weiterleitungsadresse hinzufügen falls konfiguriert + if (config?.defaultForwardEmail) { + forwardTargets.push(config.defaultForwardEmail); + } + // Prüfen ob existiert + const exists = await provider.emailExists(localPart); + if (exists.exists) { + return { + success: true, + message: `E-Mail ${exists.email} existiert bereits`, + email: exists.email, + }; + } + // Mit Mailbox erstellen + const result = await provider.createEmailWithMailbox({ + localPart, + forwardTargets, + password, + }); + return result; + } + catch (error) { + const errorMessage = error instanceof Error ? error.message : 'Unbekannter Fehler'; + return { + success: false, + error: errorMessage, + }; + } +} +// Mailbox für existierende E-Mail-Weiterleitung aktivieren +async function enableMailboxForExistingEmail(localPart, password) { + try { + const provider = await getProviderInstance(); + const result = await provider.enableMailboxForExisting({ + localPart, + password, + }); + return result; + } + catch (error) { + const errorMessage = error instanceof Error ? error.message : 'Unbekannter Fehler'; + return { + success: false, + error: errorMessage, + }; + } +} +// Mailbox-Passwort beim Provider aktualisieren +async function updateMailboxPassword(localPart, password) { + try { + const provider = await getProviderInstance(); + const result = await provider.updateMailboxPassword({ + localPart, + password, + }); + return result; + } + catch (error) { + const errorMessage = error instanceof Error ? error.message : 'Unbekannter Fehler'; + return { + success: false, + error: errorMessage, + }; + } +} +async function getImapSmtpSettings() { + const config = await getActiveProviderConfig(); + if (!config) + return null; + // Default-Server: Hostname aus der apiUrl extrahieren (z.B. rs001871.fastrootserver.de aus https://rs001871.fastrootserver.de:8443) + // Der Plesk-Server ist gleichzeitig der Mail-Server + let defaultServer; + try { + const url = new URL(config.apiUrl); + defaultServer = url.hostname; + } + catch { + // Fallback falls apiUrl ungültig + defaultServer = `mail.${config.domain}`; + } + // Verschlüsselungs-Einstellungen + const imapEncryption = (config.imapEncryption ?? 'SSL'); + const smtpEncryption = (config.smtpEncryption ?? 'SSL'); + // Ports basierend auf Verschlüsselung berechnen: + // SSL: IMAP 993, SMTP 465 + // STARTTLS: IMAP 143, SMTP 587 + // NONE: IMAP 143, SMTP 25 + // + // Standard-Ports werden IMMER basierend auf Verschlüsselung berechnet. + // Nur benutzerdefinierte Ports (nicht 993/143/465/587/25) werden aus der DB übernommen. + const getImapPort = (enc, storedPort) => { + const standardPorts = [993, 143]; + // Wenn ein nicht-standard Port gespeichert ist, diesen verwenden + if (storedPort && !standardPorts.includes(storedPort)) { + return storedPort; + } + // Sonst basierend auf Verschlüsselung + return enc === 'SSL' ? 993 : 143; + }; + const getSmtpPort = (enc, storedPort) => { + const standardPorts = [465, 587, 25]; + // Wenn ein nicht-standard Port gespeichert ist, diesen verwenden + if (storedPort && !standardPorts.includes(storedPort)) { + return storedPort; + } + // Sonst basierend auf Verschlüsselung + if (enc === 'SSL') + return 465; + if (enc === 'STARTTLS') + return 587; + return 25; // NONE + }; + return { + imapServer: config.imapServer || defaultServer, + imapPort: getImapPort(imapEncryption, config.imapPort), + imapEncryption, + smtpServer: config.smtpServer || defaultServer, + smtpPort: getSmtpPort(smtpEncryption, config.smtpPort), + smtpEncryption, + allowSelfSignedCerts: config.allowSelfSignedCerts ?? false, + domain: config.domain, + }; +} // E-Mail löschen async function deprovisionEmail(localPart) { try { @@ -284,6 +434,13 @@ async function getProviderInstanceById(id) { password, domain: dbConfig.domain, defaultForwardEmail: dbConfig.defaultForwardEmail || undefined, + imapServer: dbConfig.imapServer || undefined, + imapPort: dbConfig.imapPort || undefined, + smtpServer: dbConfig.smtpServer || undefined, + smtpPort: dbConfig.smtpPort || undefined, + imapEncryption: dbConfig.imapEncryption, + smtpEncryption: dbConfig.smtpEncryption, + allowSelfSignedCerts: dbConfig.allowSelfSignedCerts, isActive: dbConfig.isActive, isDefault: dbConfig.isDefault, }; diff --git a/backend/dist/services/emailProvider/emailProviderService.js.map b/backend/dist/services/emailProvider/emailProviderService.js.map index 14d58030..2bf98cb5 100644 --- a/backend/dist/services/emailProvider/emailProviderService.js.map +++ b/backend/dist/services/emailProvider/emailProviderService.js.map @@ -1 +1 @@ -{"version":3,"file":"emailProviderService.js","sourceRoot":"","sources":["../../../src/services/emailProvider/emailProviderService.ts"],"names":[],"mappings":"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"} \ No newline at end of file +{"version":3,"file":"emailProviderService.js","sourceRoot":"","sources":["../../../src/services/emailProvider/emailProviderService.ts"],"names":[],"mappings":"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"} \ No newline at end of file diff --git a/backend/dist/services/emailProvider/pleskProvider.d.ts b/backend/dist/services/emailProvider/pleskProvider.d.ts index 98aabb35..558bf181 100644 --- a/backend/dist/services/emailProvider/pleskProvider.d.ts +++ b/backend/dist/services/emailProvider/pleskProvider.d.ts @@ -1,4 +1,4 @@ -import { IEmailProvider, EmailProviderConfig, EmailExistsResult, EmailOperationResult, CreateEmailParams, RenameEmailParams } from './types.js'; +import { IEmailProvider, EmailProviderConfig, EmailExistsResult, EmailOperationResult, CreateEmailParams, CreateEmailWithMailboxParams, CreateEmailWithMailboxResult, EnableMailboxParams, UpdateMailboxPasswordParams, RenameEmailParams } from './types.js'; export declare class PleskEmailProvider implements IEmailProvider { readonly type = "PLESK"; private config; @@ -8,6 +8,9 @@ export declare class PleskEmailProvider implements IEmailProvider { testConnection(): Promise; emailExists(localPart: string): Promise; createEmail(params: CreateEmailParams): Promise; + createEmailWithMailbox(params: CreateEmailWithMailboxParams): Promise; + enableMailboxForExisting(params: EnableMailboxParams): Promise; + updateMailboxPassword(params: UpdateMailboxPasswordParams): Promise; deleteEmail(localPart: string): Promise; renameEmail(params: RenameEmailParams): Promise; updateForwardTargets(localPart: string, targets: string[]): Promise; diff --git a/backend/dist/services/emailProvider/pleskProvider.d.ts.map b/backend/dist/services/emailProvider/pleskProvider.d.ts.map index 1eb64529..d048a748 100644 --- a/backend/dist/services/emailProvider/pleskProvider.d.ts.map +++ b/backend/dist/services/emailProvider/pleskProvider.d.ts.map @@ -1 +1 @@ -{"version":3,"file":"pleskProvider.d.ts","sourceRoot":"","sources":["../../../src/services/emailProvider/pleskProvider.ts"],"names":[],"mappings":"AAGA,OAAO,EACL,cAAc,EACd,mBAAmB,EACnB,iBAAiB,EACjB,oBAAoB,EACpB,iBAAiB,EACjB,iBAAiB,EAClB,MAAM,YAAY,CAAC;AAiBpB,qBAAa,kBAAmB,YAAW,cAAc;IACvD,QAAQ,CAAC,IAAI,WAAW;IACxB,OAAO,CAAC,MAAM,CAAsB;gBAExB,MAAM,EAAE,mBAAmB;IAKvC,OAAO,KAAK,OAAO,GAGlB;YAGa,OAAO;IAsFf,cAAc,IAAI,OAAO,CAAC,IAAI,CAAC;IAmB/B,WAAW,CAAC,SAAS,EAAE,MAAM,GAAG,OAAO,CAAC,iBAAiB,CAAC;IA8C1D,WAAW,CAAC,MAAM,EAAE,iBAAiB,GAAG,OAAO,CAAC,oBAAoB,CAAC;IAuCrE,WAAW,CAAC,SAAS,EAAE,MAAM,GAAG,OAAO,CAAC,oBAAoB,CAAC;IAgC7D,WAAW,CAAC,MAAM,EAAE,iBAAiB,GAAG,OAAO,CAAC,oBAAoB,CAAC;IA2CrE,oBAAoB,CACxB,SAAS,EAAE,MAAM,EACjB,OAAO,EAAE,MAAM,EAAE,GAChB,OAAO,CAAC,oBAAoB,CAAC;CAmCjC"} \ No newline at end of file +{"version":3,"file":"pleskProvider.d.ts","sourceRoot":"","sources":["../../../src/services/emailProvider/pleskProvider.ts"],"names":[],"mappings":"AAGA,OAAO,EACL,cAAc,EACd,mBAAmB,EACnB,iBAAiB,EACjB,oBAAoB,EACpB,iBAAiB,EACjB,4BAA4B,EAC5B,4BAA4B,EAC5B,mBAAmB,EACnB,2BAA2B,EAC3B,iBAAiB,EAClB,MAAM,YAAY,CAAC;AAiBpB,qBAAa,kBAAmB,YAAW,cAAc;IACvD,QAAQ,CAAC,IAAI,WAAW;IACxB,OAAO,CAAC,MAAM,CAAsB;gBAExB,MAAM,EAAE,mBAAmB;IAKvC,OAAO,KAAK,OAAO,GAGlB;YAGa,OAAO;IAsFf,cAAc,IAAI,OAAO,CAAC,IAAI,CAAC;IAmB/B,WAAW,CAAC,SAAS,EAAE,MAAM,GAAG,OAAO,CAAC,iBAAiB,CAAC;IAyD1D,WAAW,CAAC,MAAM,EAAE,iBAAiB,GAAG,OAAO,CAAC,oBAAoB,CAAC;IAwCrE,sBAAsB,CAAC,MAAM,EAAE,4BAA4B,GAAG,OAAO,CAAC,4BAA4B,CAAC;IA2CnG,wBAAwB,CAAC,MAAM,EAAE,mBAAmB,GAAG,OAAO,CAAC,oBAAoB,CAAC;IAwCpF,qBAAqB,CAAC,MAAM,EAAE,2BAA2B,GAAG,OAAO,CAAC,oBAAoB,CAAC;IAsCzF,WAAW,CAAC,SAAS,EAAE,MAAM,GAAG,OAAO,CAAC,oBAAoB,CAAC;IAgC7D,WAAW,CAAC,MAAM,EAAE,iBAAiB,GAAG,OAAO,CAAC,oBAAoB,CAAC;IA2CrE,oBAAoB,CACxB,SAAS,EAAE,MAAM,EACjB,OAAO,EAAE,MAAM,EAAE,GAChB,OAAO,CAAC,oBAAoB,CAAC;CAoCjC"} \ No newline at end of file diff --git a/backend/dist/services/emailProvider/pleskProvider.js b/backend/dist/services/emailProvider/pleskProvider.js index 9c2fd8f1..8a88e7b4 100644 --- a/backend/dist/services/emailProvider/pleskProvider.js +++ b/backend/dist/services/emailProvider/pleskProvider.js @@ -137,9 +137,18 @@ class PleskEmailProvider { } // stdout sollte die Mail-Infos enthalten const exists = result.stdout?.toLowerCase().includes(localPart.toLowerCase()); + // Mailbox-Status aus stdout parsen (Format: "Mailbox: true" oder "Mailbox: false") + let hasMailbox; + if (exists && result.stdout) { + const mailboxMatch = result.stdout.match(/Mailbox:\s*(true|false)/i); + if (mailboxMatch) { + hasMailbox = mailboxMatch[1].toLowerCase() === 'true'; + } + } return { exists, email: exists ? email : undefined, + hasMailbox, }; } catch (error) { @@ -169,11 +178,12 @@ class PleskEmailProvider { } // Plesk CLI API: Mail-Account mit Weiterleitung erstellen // Verwendet den CLI-Wrapper unter /api/v2/cli/mail/call + // Format für -forwarding-addresses: "add:email1,email2" oder "set:email1,email2" await this.request('POST', '/api/v2/cli/mail/call', { params: [ '--create', email, '-forwarding', 'true', - '-forwarding-addresses', forwardTargets.join(','), + '-forwarding-addresses', `add:${forwardTargets.join(',')}`, '-mailbox', 'false', ], }); @@ -191,6 +201,118 @@ class PleskEmailProvider { }; } } + async createEmailWithMailbox(params) { + const { localPart, forwardTargets, password } = params; + const email = `${localPart}@${this.config.domain}`; + try { + // Prüfen ob schon existiert + const exists = await this.emailExists(localPart); + if (exists.exists) { + return { + success: false, + error: `E-Mail ${email} existiert bereits`, + }; + } + // Plesk CLI API: Mail-Account mit echter Mailbox erstellen + // -mailbox true: Echte Mailbox (IMAP/SMTP-Zugang) + // -passwd: Passwort für die Mailbox + // -forwarding true: Zusätzlich Weiterleitung aktivieren + await this.request('POST', '/api/v2/cli/mail/call', { + params: [ + '--create', email, + '-mailbox', 'true', + '-passwd', password, + '-forwarding', 'true', + '-forwarding-addresses', `add:${forwardTargets.join(',')}`, + ], + }); + return { + success: true, + message: `E-Mail ${email} mit Mailbox erfolgreich erstellt`, + email, + }; + } + catch (error) { + const errorMessage = error instanceof Error ? error.message : 'Unbekannter Fehler'; + console.error('Plesk createEmailWithMailbox error:', error); + return { + success: false, + error: `Fehler beim Erstellen der E-Mail mit Mailbox: ${errorMessage}`, + }; + } + } + async enableMailboxForExisting(params) { + const { localPart, password } = params; + const email = `${localPart}@${this.config.domain}`; + try { + // Prüfen ob E-Mail existiert + const exists = await this.emailExists(localPart); + if (!exists.exists) { + return { + success: false, + error: `E-Mail ${email} nicht gefunden`, + }; + } + // Plesk CLI API: Mailbox für existierende E-Mail aktivieren + // --update: Existierende E-Mail aktualisieren + // -mailbox true: Mailbox aktivieren + // -passwd: Passwort für die Mailbox setzen + await this.request('POST', '/api/v2/cli/mail/call', { + params: [ + '--update', email, + '-mailbox', 'true', + '-passwd', password, + ], + }); + return { + success: true, + message: `Mailbox für ${email} erfolgreich aktiviert`, + }; + } + catch (error) { + const errorMessage = error instanceof Error ? error.message : 'Unbekannter Fehler'; + console.error('Plesk enableMailboxForExisting error:', error); + return { + success: false, + error: `Fehler beim Aktivieren der Mailbox: ${errorMessage}`, + }; + } + } + async updateMailboxPassword(params) { + const { localPart, password } = params; + const email = `${localPart}@${this.config.domain}`; + try { + // Prüfen ob E-Mail existiert + const exists = await this.emailExists(localPart); + if (!exists.exists) { + return { + success: false, + error: `E-Mail ${email} nicht gefunden`, + }; + } + // Plesk CLI API: Passwort für existierende E-Mail aktualisieren + // --update: Existierende E-Mail aktualisieren + // -passwd: Neues Passwort setzen + await this.request('POST', '/api/v2/cli/mail/call', { + params: [ + '--update', email, + '-passwd', password, + ], + }); + return { + success: true, + message: `Passwort für ${email} erfolgreich aktualisiert`, + }; + } + catch (error) { + const errorMessage = error instanceof Error ? error.message : 'Unbekannter Fehler'; + console.error('Plesk updateMailboxPassword error:', error); + return { + success: false, + error: `Fehler beim Aktualisieren des Passworts: ${errorMessage}`, + }; + } + } async deleteEmail(localPart) { const email = `${localPart}@${this.config.domain}`; try { @@ -271,11 +393,12 @@ class PleskEmailProvider { }; } // Plesk CLI API: Weiterleitungsziele aktualisieren + // Format für -forwarding-addresses: "set:email1,email2" ersetzt alle Adressen await this.request('POST', '/api/v2/cli/mail/call', { params: [ '--update', email, '-forwarding', 'true', - '-forwarding-addresses', targets.join(','), + '-forwarding-addresses', `set:${targets.join(',')}`, ], }); return { diff --git a/backend/dist/services/emailProvider/pleskProvider.js.map b/backend/dist/services/emailProvider/pleskProvider.js.map index 14f46b00..a05a332d 100644 --- a/backend/dist/services/emailProvider/pleskProvider.js.map +++ b/backend/dist/services/emailProvider/pleskProvider.js.map @@ -1 +1 @@ -{"version":3,"file":"pleskProvider.js","sourceRoot":"","sources":["../../../src/services/emailProvider/pleskProvider.ts"],"names":[],"mappings":"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"} \ No newline at end of file +{"version":3,"file":"pleskProvider.js","sourceRoot":"","sources":["../../../src/services/emailProvider/pleskProvider.ts"],"names":[],"mappings":"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"} \ No newline at end of file diff --git a/backend/dist/services/emailProvider/types.d.ts b/backend/dist/services/emailProvider/types.d.ts index cf496d2a..7c3ec4e2 100644 --- a/backend/dist/services/emailProvider/types.d.ts +++ b/backend/dist/services/emailProvider/types.d.ts @@ -1,3 +1,4 @@ +export type MailEncryption = 'SSL' | 'STARTTLS' | 'NONE'; export interface EmailForwardTarget { email: string; } @@ -5,6 +6,22 @@ export interface CreateEmailParams { localPart: string; forwardTargets: string[]; } +export interface CreateEmailWithMailboxParams { + localPart: string; + forwardTargets: string[]; + password: string; +} +export interface CreateEmailWithMailboxResult extends EmailOperationResult { + email?: string; +} +export interface EnableMailboxParams { + localPart: string; + password: string; +} +export interface UpdateMailboxPasswordParams { + localPart: string; + password: string; +} export interface RenameEmailParams { oldLocalPart: string; newLocalPart: string; @@ -12,6 +29,7 @@ export interface RenameEmailParams { export interface EmailExistsResult { exists: boolean; email?: string; + hasMailbox?: boolean; } export interface EmailOperationResult { success: boolean; @@ -23,6 +41,9 @@ export interface IEmailProvider { testConnection(): Promise; emailExists(localPart: string): Promise; createEmail(params: CreateEmailParams): Promise; + createEmailWithMailbox(params: CreateEmailWithMailboxParams): Promise; + enableMailboxForExisting(params: EnableMailboxParams): Promise; + updateMailboxPassword(params: UpdateMailboxPasswordParams): Promise; deleteEmail(localPart: string): Promise; renameEmail(params: RenameEmailParams): Promise; updateForwardTargets(localPart: string, targets: string[]): Promise; @@ -37,6 +58,13 @@ export interface EmailProviderConfig { password?: string; domain: string; defaultForwardEmail?: string; + imapServer?: string; + imapPort?: number; + smtpServer?: string; + smtpPort?: number; + imapEncryption?: MailEncryption; + smtpEncryption?: MailEncryption; + allowSelfSignedCerts?: boolean; isActive: boolean; isDefault: boolean; } diff --git a/backend/dist/services/emailProvider/types.d.ts.map b/backend/dist/services/emailProvider/types.d.ts.map index c40d734e..66b4db2d 100644 --- a/backend/dist/services/emailProvider/types.d.ts.map +++ b/backend/dist/services/emailProvider/types.d.ts.map @@ -1 +1 @@ -{"version":3,"file":"types.d.ts","sourceRoot":"","sources":["../../../src/services/emailProvider/types.ts"],"names":[],"mappings":"AAEA,MAAM,WAAW,kBAAkB;IACjC,KAAK,EAAE,MAAM,CAAC;CACf;AAED,MAAM,WAAW,iBAAiB;IAChC,SAAS,EAAE,MAAM,CAAC;IAClB,cAAc,EAAE,MAAM,EAAE,CAAC;CAC1B;AAED,MAAM,WAAW,iBAAiB;IAChC,YAAY,EAAE,MAAM,CAAC;IACrB,YAAY,EAAE,MAAM,CAAC;CACtB;AAED,MAAM,WAAW,iBAAiB;IAChC,MAAM,EAAE,OAAO,CAAC;IAChB,KAAK,CAAC,EAAE,MAAM,CAAC;CAChB;AAED,MAAM,WAAW,oBAAoB;IACnC,OAAO,EAAE,OAAO,CAAC;IACjB,OAAO,CAAC,EAAE,MAAM,CAAC;IACjB,KAAK,CAAC,EAAE,MAAM,CAAC;CAChB;AAGD,MAAM,WAAW,cAAc;IAE7B,QAAQ,CAAC,IAAI,EAAE,MAAM,CAAC;IAGtB,cAAc,IAAI,OAAO,CAAC,IAAI,CAAC,CAAC;IAGhC,WAAW,CAAC,SAAS,EAAE,MAAM,GAAG,OAAO,CAAC,iBAAiB,CAAC,CAAC;IAG3D,WAAW,CAAC,MAAM,EAAE,iBAAiB,GAAG,OAAO,CAAC,oBAAoB,CAAC,CAAC;IAGtE,WAAW,CAAC,SAAS,EAAE,MAAM,GAAG,OAAO,CAAC,oBAAoB,CAAC,CAAC;IAG9D,WAAW,CAAC,MAAM,EAAE,iBAAiB,GAAG,OAAO,CAAC,oBAAoB,CAAC,CAAC;IAGtE,oBAAoB,CAAC,SAAS,EAAE,MAAM,EAAE,OAAO,EAAE,MAAM,EAAE,GAAG,OAAO,CAAC,oBAAoB,CAAC,CAAC;CAC3F;AAGD,MAAM,WAAW,mBAAmB;IAClC,EAAE,EAAE,MAAM,CAAC;IACX,IAAI,EAAE,MAAM,CAAC;IACb,IAAI,EAAE,OAAO,GAAG,QAAQ,GAAG,aAAa,CAAC;IACzC,MAAM,EAAE,MAAM,CAAC;IACf,MAAM,CAAC,EAAE,MAAM,CAAC;IAChB,QAAQ,CAAC,EAAE,MAAM,CAAC;IAClB,QAAQ,CAAC,EAAE,MAAM,CAAC;IAClB,MAAM,EAAE,MAAM,CAAC;IACf,mBAAmB,CAAC,EAAE,MAAM,CAAC;IAC7B,QAAQ,EAAE,OAAO,CAAC;IAClB,SAAS,EAAE,OAAO,CAAC;CACpB"} \ No newline at end of file +{"version":3,"file":"types.d.ts","sourceRoot":"","sources":["../../../src/services/emailProvider/types.ts"],"names":[],"mappings":"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"} \ No newline at end of file diff --git a/backend/dist/services/stressfreiEmail.service.d.ts b/backend/dist/services/stressfreiEmail.service.d.ts index eede81ca..10196618 100644 --- a/backend/dist/services/stressfreiEmail.service.d.ts +++ b/backend/dist/services/stressfreiEmail.service.d.ts @@ -6,10 +6,21 @@ export declare function getEmailsByCustomerId(customerId: number, includeInactiv createdAt: Date; updatedAt: Date; notes: string | null; + hasMailbox: boolean; platform: string | null; isProvisioned: boolean; provisionedAt: Date | null; provisionError: string | null; + emailPasswordEncrypted: string | null; +}[]>; +export declare function getEmailsWithMailboxByCustomerId(customerId: number): Promise<{ + id: number; + email: string; + notes: string | null; + _count: { + cachedEmails: number; + }; + hasMailbox: boolean; }[]>; export declare function getEmailById(id: number): Promise<{ id: number; @@ -19,17 +30,14 @@ export declare function getEmailById(id: number): Promise<{ createdAt: Date; updatedAt: Date; notes: string | null; + hasMailbox: boolean; platform: string | null; isProvisioned: boolean; provisionedAt: Date | null; provisionError: string | null; + emailPasswordEncrypted: string | null; } | null>; -export declare function createEmail(data: { - customerId: number; - email: string; - platform?: string; - notes?: string; -}): Promise<{ +export declare function getEmailWithMailboxById(id: number): Promise<{ id: number; email: string; customerId: number; @@ -37,10 +45,32 @@ export declare function createEmail(data: { createdAt: Date; updatedAt: Date; notes: string | null; + hasMailbox: boolean; + platform: string | null; + emailPasswordEncrypted: string | null; +} | null>; +export interface CreateEmailData { + customerId: number; + email: string; + platform?: string; + notes?: string; + provisionAtProvider?: boolean; + createMailbox?: boolean; +} +export declare function createEmail(data: CreateEmailData): Promise<{ + id: number; + email: string; + customerId: number; + isActive: boolean; + createdAt: Date; + updatedAt: Date; + notes: string | null; + hasMailbox: boolean; platform: string | null; isProvisioned: boolean; provisionedAt: Date | null; provisionError: string | null; + emailPasswordEncrypted: string | null; }>; export declare function updateEmail(id: number, data: { email?: string; @@ -55,10 +85,12 @@ export declare function updateEmail(id: number, data: { createdAt: Date; updatedAt: Date; notes: string | null; + hasMailbox: boolean; platform: string | null; isProvisioned: boolean; provisionedAt: Date | null; provisionError: string | null; + emailPasswordEncrypted: string | null; }>; export declare function deleteEmail(id: number): Promise<{ id: number; @@ -68,9 +100,27 @@ export declare function deleteEmail(id: number): Promise<{ createdAt: Date; updatedAt: Date; notes: string | null; + hasMailbox: boolean; platform: string | null; isProvisioned: boolean; provisionedAt: Date | null; provisionError: string | null; + emailPasswordEncrypted: string | null; +}>; +export declare function enableMailbox(id: number): Promise<{ + success: boolean; + error?: string; +}>; +export declare function syncMailboxStatus(id: number): Promise<{ + success: boolean; + hasMailbox?: boolean; + wasUpdated?: boolean; + error?: string; +}>; +export declare function getDecryptedPassword(id: number): Promise; +export declare function resetMailboxPassword(id: number): Promise<{ + success: boolean; + password?: string; + error?: string; }>; //# sourceMappingURL=stressfreiEmail.service.d.ts.map \ No newline at end of file diff --git a/backend/dist/services/stressfreiEmail.service.d.ts.map b/backend/dist/services/stressfreiEmail.service.d.ts.map index 1c9b8781..b37603c3 100644 --- a/backend/dist/services/stressfreiEmail.service.d.ts.map +++ b/backend/dist/services/stressfreiEmail.service.d.ts.map @@ -1 +1 @@ -{"version":3,"file":"stressfreiEmail.service.d.ts","sourceRoot":"","sources":["../../src/services/stressfreiEmail.service.ts"],"names":[],"mappings":"AAIA,wBAAsB,qBAAqB,CAAC,UAAU,EAAE,MAAM,EAAE,eAAe,UAAQ;;;;;;;;;;;;KAStF;AAED,wBAAsB,YAAY,CAAC,EAAE,EAAE,MAAM;;;;;;;;;;;;UAI5C;AAED,wBAAsB,WAAW,CAAC,IAAI,EAAE;IACtC,UAAU,EAAE,MAAM,CAAC;IACnB,KAAK,EAAE,MAAM,CAAC;IACd,QAAQ,CAAC,EAAE,MAAM,CAAC;IAClB,KAAK,CAAC,EAAE,MAAM,CAAC;CAChB;;;;;;;;;;;;GAOA;AAED,wBAAsB,WAAW,CAC/B,EAAE,EAAE,MAAM,EACV,IAAI,EAAE;IACJ,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,QAAQ,CAAC,EAAE,MAAM,CAAC;IAClB,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,QAAQ,CAAC,EAAE,OAAO,CAAC;CACpB;;;;;;;;;;;;GAMF;AAED,wBAAsB,WAAW,CAAC,EAAE,EAAE,MAAM;;;;;;;;;;;;GAE3C"} \ No newline at end of file +{"version":3,"file":"stressfreiEmail.service.d.ts","sourceRoot":"","sources":["../../src/services/stressfreiEmail.service.ts"],"names":[],"mappings":"AAcA,wBAAsB,qBAAqB,CAAC,UAAU,EAAE,MAAM,EAAE,eAAe,UAAQ;;;;;;;;;;;;;;KAStF;AAGD,wBAAsB,gCAAgC,CAAC,UAAU,EAAE,MAAM;;;;;;;;KAoBxE;AAED,wBAAsB,YAAY,CAAC,EAAE,EAAE,MAAM;;;;;;;;;;;;;;UAI5C;AAGD,wBAAsB,uBAAuB,CAAC,EAAE,EAAE,MAAM;;;;;;;;;;;UAgBvD;AAED,MAAM,WAAW,eAAe;IAC9B,UAAU,EAAE,MAAM,CAAC;IACnB,KAAK,EAAE,MAAM,CAAC;IACd,QAAQ,CAAC,EAAE,MAAM,CAAC;IAClB,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,mBAAmB,CAAC,EAAE,OAAO,CAAC;IAC9B,aAAa,CAAC,EAAE,OAAO,CAAC;CACzB;AAED,wBAAsB,WAAW,CAAC,IAAI,EAAE,eAAe;;;;;;;;;;;;;;GAuDtD;AAED,wBAAsB,WAAW,CAC/B,EAAE,EAAE,MAAM,EACV,IAAI,EAAE;IACJ,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,QAAQ,CAAC,EAAE,MAAM,CAAC;IAClB,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,QAAQ,CAAC,EAAE,OAAO,CAAC;CACpB;;;;;;;;;;;;;;GAMF;AAED,wBAAsB,WAAW,CAAC,EAAE,EAAE,MAAM;;;;;;;;;;;;;;GAE3C;AAGD,wBAAsB,aAAa,CAAC,EAAE,EAAE,MAAM,GAAG,OAAO,CAAC;IAAE,OAAO,EAAE,OAAO,CAAC;IAAC,KAAK,CAAC,EAAE,MAAM,CAAA;CAAE,CAAC,CAmC7F;AAGD,wBAAsB,iBAAiB,CAAC,EAAE,EAAE,MAAM,GAAG,OAAO,CAAC;IAC3D,OAAO,EAAE,OAAO,CAAC;IACjB,UAAU,CAAC,EAAE,OAAO,CAAC;IACrB,UAAU,CAAC,EAAE,OAAO,CAAC;IACrB,KAAK,CAAC,EAAE,MAAM,CAAA;CACf,CAAC,CAgCD;AAGD,wBAAsB,oBAAoB,CAAC,EAAE,EAAE,MAAM,GAAG,OAAO,CAAC,MAAM,GAAG,IAAI,CAAC,CAgB7E;AAGD,wBAAsB,oBAAoB,CAAC,EAAE,EAAE,MAAM,GAAG,OAAO,CAAC;IAAE,OAAO,EAAE,OAAO,CAAC;IAAC,QAAQ,CAAC,EAAE,MAAM,CAAC;IAAC,KAAK,CAAC,EAAE,MAAM,CAAA;CAAE,CAAC,CAiCvH"} \ No newline at end of file diff --git a/backend/dist/services/stressfreiEmail.service.js b/backend/dist/services/stressfreiEmail.service.js index e6a06f96..85a585d9 100644 --- a/backend/dist/services/stressfreiEmail.service.js +++ b/backend/dist/services/stressfreiEmail.service.js @@ -1,11 +1,20 @@ "use strict"; Object.defineProperty(exports, "__esModule", { value: true }); exports.getEmailsByCustomerId = getEmailsByCustomerId; +exports.getEmailsWithMailboxByCustomerId = getEmailsWithMailboxByCustomerId; exports.getEmailById = getEmailById; +exports.getEmailWithMailboxById = getEmailWithMailboxById; exports.createEmail = createEmail; exports.updateEmail = updateEmail; exports.deleteEmail = deleteEmail; +exports.enableMailbox = enableMailbox; +exports.syncMailboxStatus = syncMailboxStatus; +exports.getDecryptedPassword = getDecryptedPassword; +exports.resetMailboxPassword = resetMailboxPassword; const client_1 = require("@prisma/client"); +const encryption_js_1 = require("../utils/encryption.js"); +const emailProviderService_js_1 = require("./emailProvider/emailProviderService.js"); +const passwordGenerator_js_1 = require("../utils/passwordGenerator.js"); const prisma = new client_1.PrismaClient(); async function getEmailsByCustomerId(customerId, includeInactive = false) { const where = { customerId }; @@ -17,16 +26,96 @@ async function getEmailsByCustomerId(customerId, includeInactive = false) { orderBy: { createdAt: 'desc' }, }); } +// Mit Mailbox-Status für E-Mail-Client +async function getEmailsWithMailboxByCustomerId(customerId) { + return prisma.stressfreiEmail.findMany({ + where: { + customerId, + isActive: true, + hasMailbox: true, + }, + select: { + id: true, + email: true, + notes: true, + hasMailbox: true, + _count: { + select: { + cachedEmails: true, + }, + }, + }, + orderBy: { email: 'asc' }, + }); +} async function getEmailById(id) { return prisma.stressfreiEmail.findUnique({ where: { id }, }); } +// E-Mail mit Mailbox-Status laden +async function getEmailWithMailboxById(id) { + return prisma.stressfreiEmail.findUnique({ + where: { id }, + select: { + id: true, + customerId: true, + email: true, + platform: true, + notes: true, + isActive: true, + hasMailbox: true, + emailPasswordEncrypted: true, + createdAt: true, + updatedAt: true, + }, + }); +} async function createEmail(data) { + const { provisionAtProvider, createMailbox, ...emailData } = data; + // Falls beim Provider anlegen gewünscht + if (provisionAtProvider) { + // Kunde laden für Weiterleitung + const customer = await prisma.customer.findUnique({ + where: { id: data.customerId }, + select: { email: true }, + }); + if (!customer?.email) { + throw new Error('Kunde hat keine E-Mail-Adresse für Weiterleitung'); + } + // LocalPart extrahieren + const localPart = data.email.split('@')[0]; + if (createMailbox) { + // Mit echter Mailbox anlegen + const password = (0, passwordGenerator_js_1.generateSecurePassword)(); + const result = await (0, emailProviderService_js_1.provisionEmailWithMailbox)(localPart, customer.email, password); + if (!result.success) { + throw new Error(result.error || 'Fehler beim Anlegen der Mailbox'); + } + // Passwort verschlüsseln und speichern + const passwordEncrypted = (0, encryption_js_1.encrypt)(password); + return prisma.stressfreiEmail.create({ + data: { + ...emailData, + isActive: true, + hasMailbox: true, + emailPasswordEncrypted: passwordEncrypted, + }, + }); + } + else { + // Nur Weiterleitung anlegen + const result = await (0, emailProviderService_js_1.provisionEmail)(localPart, customer.email); + if (!result.success && !result.message?.includes('existiert bereits')) { + throw new Error(result.error || 'Fehler beim Anlegen der E-Mail'); + } + } + } return prisma.stressfreiEmail.create({ data: { - ...data, + ...emailData, isActive: true, + hasMailbox: createMailbox || false, }, }); } @@ -39,4 +128,105 @@ async function updateEmail(id, data) { async function deleteEmail(id) { return prisma.stressfreiEmail.delete({ where: { id } }); } +// Mailbox nachträglich aktivieren (für existierende E-Mail-Weiterleitung) +async function enableMailbox(id) { + const stressfreiEmail = await prisma.stressfreiEmail.findUnique({ + where: { id }, + }); + if (!stressfreiEmail) { + return { success: false, error: 'StressfreiEmail nicht gefunden' }; + } + if (stressfreiEmail.hasMailbox) { + return { success: false, error: 'Mailbox ist bereits aktiviert' }; + } + const localPart = stressfreiEmail.email.split('@')[0]; + const password = (0, passwordGenerator_js_1.generateSecurePassword)(); + // Mailbox für existierende E-Mail aktivieren (nicht neu erstellen!) + const result = await (0, emailProviderService_js_1.enableMailboxForExistingEmail)(localPart, password); + if (!result.success) { + return { success: false, error: result.error || 'Fehler beim Aktivieren der Mailbox' }; + } + // Passwort verschlüsseln und speichern + const passwordEncrypted = (0, encryption_js_1.encrypt)(password); + await prisma.stressfreiEmail.update({ + where: { id }, + data: { + hasMailbox: true, + emailPasswordEncrypted: passwordEncrypted, + }, + }); + return { success: true }; +} +// Mailbox-Status mit Provider synchronisieren +async function syncMailboxStatus(id) { + const stressfreiEmail = await prisma.stressfreiEmail.findUnique({ + where: { id }, + select: { email: true, hasMailbox: true }, + }); + if (!stressfreiEmail) { + return { success: false, error: 'StressfreiEmail nicht gefunden' }; + } + const localPart = stressfreiEmail.email.split('@')[0]; + // Provider-Status prüfen + const providerStatus = await (0, emailProviderService_js_1.checkEmailExists)(localPart); + if (!providerStatus.exists) { + return { success: true, hasMailbox: false, wasUpdated: false }; + } + const providerHasMailbox = providerStatus.hasMailbox === true; + // DB aktualisieren wenn Status abweicht + if (stressfreiEmail.hasMailbox !== providerHasMailbox) { + await prisma.stressfreiEmail.update({ + where: { id }, + data: { hasMailbox: providerHasMailbox }, + }); + console.log(`Mailbox-Status für ${stressfreiEmail.email} aktualisiert: ${stressfreiEmail.hasMailbox} -> ${providerHasMailbox}`); + return { success: true, hasMailbox: providerHasMailbox, wasUpdated: true }; + } + return { success: true, hasMailbox: providerHasMailbox, wasUpdated: false }; +} +// Passwort für IMAP/SMTP-Zugang entschlüsseln (nur für autorisierte Nutzung) +async function getDecryptedPassword(id) { + const stressfreiEmail = await prisma.stressfreiEmail.findUnique({ + where: { id }, + select: { emailPasswordEncrypted: true }, + }); + if (!stressfreiEmail?.emailPasswordEncrypted) { + return null; + } + try { + return (0, encryption_js_1.decrypt)(stressfreiEmail.emailPasswordEncrypted); + } + catch { + console.error('Fehler beim Entschlüsseln des Passworts'); + return null; + } +} +// Passwort neu generieren und beim Provider setzen +async function resetMailboxPassword(id) { + const stressfreiEmail = await prisma.stressfreiEmail.findUnique({ + where: { id }, + select: { email: true, hasMailbox: true }, + }); + if (!stressfreiEmail) { + return { success: false, error: 'StressfreiEmail nicht gefunden' }; + } + if (!stressfreiEmail.hasMailbox) { + return { success: false, error: 'Keine Mailbox für diese E-Mail-Adresse' }; + } + // Neues Passwort generieren + const newPassword = (0, passwordGenerator_js_1.generateSecurePassword)(); + const localPart = stressfreiEmail.email.split('@')[0]; + // Passwort beim Provider ändern + const providerResult = await (0, emailProviderService_js_1.updateMailboxPassword)(localPart, newPassword); + if (!providerResult.success) { + return { success: false, error: providerResult.error || 'Fehler beim Aktualisieren des Passworts beim Provider' }; + } + // Passwort verschlüsseln und lokal speichern + const passwordEncrypted = (0, encryption_js_1.encrypt)(newPassword); + await prisma.stressfreiEmail.update({ + where: { id }, + data: { emailPasswordEncrypted: passwordEncrypted }, + }); + return { success: true, password: newPassword }; +} //# sourceMappingURL=stressfreiEmail.service.js.map \ No newline at end of file diff --git a/backend/dist/services/stressfreiEmail.service.js.map b/backend/dist/services/stressfreiEmail.service.js.map index aa3212d0..baa93dd4 100644 --- a/backend/dist/services/stressfreiEmail.service.js.map +++ b/backend/dist/services/stressfreiEmail.service.js.map @@ -1 +1 @@ -{"version":3,"file":"stressfreiEmail.service.js","sourceRoot":"","sources":["../../src/services/stressfreiEmail.service.ts"],"names":[],"mappings":";;AAIA,sDASC;AAED,oCAIC;AAED,kCAYC;AAED,kCAaC;AAED,kCAEC;AApDD,2CAA8C;AAE9C,MAAM,MAAM,GAAG,IAAI,qBAAY,EAAE,CAAC;AAE3B,KAAK,UAAU,qBAAqB,CAAC,UAAkB,EAAE,eAAe,GAAG,KAAK;IACrF,MAAM,KAAK,GAA4B,EAAE,UAAU,EAAE,CAAC;IACtD,IAAI,CAAC,eAAe,EAAE,CAAC;QACrB,KAAK,CAAC,QAAQ,GAAG,IAAI,CAAC;IACxB,CAAC;IACD,OAAO,MAAM,CAAC,eAAe,CAAC,QAAQ,CAAC;QACrC,KAAK;QACL,OAAO,EAAE,EAAE,SAAS,EAAE,MAAM,EAAE;KAC/B,CAAC,CAAC;AACL,CAAC;AAEM,KAAK,UAAU,YAAY,CAAC,EAAU;IAC3C,OAAO,MAAM,CAAC,eAAe,CAAC,UAAU,CAAC;QACvC,KAAK,EAAE,EAAE,EAAE,EAAE;KACd,CAAC,CAAC;AACL,CAAC;AAEM,KAAK,UAAU,WAAW,CAAC,IAKjC;IACC,OAAO,MAAM,CAAC,eAAe,CAAC,MAAM,CAAC;QACnC,IAAI,EAAE;YACJ,GAAG,IAAI;YACP,QAAQ,EAAE,IAAI;SACf;KACF,CAAC,CAAC;AACL,CAAC;AAEM,KAAK,UAAU,WAAW,CAC/B,EAAU,EACV,IAKC;IAED,OAAO,MAAM,CAAC,eAAe,CAAC,MAAM,CAAC;QACnC,KAAK,EAAE,EAAE,EAAE,EAAE;QACb,IAAI;KACL,CAAC,CAAC;AACL,CAAC;AAEM,KAAK,UAAU,WAAW,CAAC,EAAU;IAC1C,OAAO,MAAM,CAAC,eAAe,CAAC,MAAM,CAAC,EAAE,KAAK,EAAE,EAAE,EAAE,EAAE,EAAE,CAAC,CAAC;AAC1D,CAAC"} \ No newline at end of file +{"version":3,"file":"stressfreiEmail.service.js","sourceRoot":"","sources":["../../src/services/stressfreiEmail.service.ts"],"names":[],"mappings":"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"} \ No newline at end of file diff --git a/backend/dist/services/user.service.d.ts b/backend/dist/services/user.service.d.ts index 148c38dc..ff92e3c9 100644 --- a/backend/dist/services/user.service.d.ts +++ b/backend/dist/services/user.service.d.ts @@ -71,6 +71,7 @@ export declare function createUser(data: { lastName: string; roleIds: number[]; customerId?: number; + hasDeveloperAccess?: boolean; }): Promise<{ id: number; email: string; @@ -137,6 +138,7 @@ export declare function deleteUser(id: number): Promise<{ firstName: string; lastName: string; isActive: boolean; + tokenInvalidatedAt: Date | null; createdAt: Date; updatedAt: Date; }>; diff --git a/backend/dist/services/user.service.d.ts.map b/backend/dist/services/user.service.d.ts.map index be467df4..f4ceee54 100644 --- a/backend/dist/services/user.service.d.ts.map +++ b/backend/dist/services/user.service.d.ts.map @@ -1 +1 @@ -{"version":3,"file":"user.service.d.ts","sourceRoot":"","sources":["../../src/services/user.service.ts"],"names":[],"mappings":"AAMA,MAAM,WAAW,WAAW;IAC1B,MAAM,CAAC,EAAE,MAAM,CAAC;IAChB,QAAQ,CAAC,EAAE,OAAO,CAAC;IACnB,MAAM,CAAC,EAAE,MAAM,CAAC;IAChB,IAAI,CAAC,EAAE,MAAM,CAAC;IACd,KAAK,CAAC,EAAE,MAAM,CAAC;CAChB;AAED,wBAAsB,WAAW,CAAC,OAAO,EAAE,WAAW;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GAqErD;AAED,wBAAsB,WAAW,CAAC,EAAE,EAAE,MAAM;;;;;;;;;;;;;;;;;;;;;;;;;;;;UA0C3C;AAED,wBAAsB,UAAU,CAAC,IAAI,EAAE;IACrC,KAAK,EAAE,MAAM,CAAC;IACd,QAAQ,EAAE,MAAM,CAAC;IACjB,SAAS,EAAE,MAAM,CAAC;IAClB,QAAQ,EAAE,MAAM,CAAC;IACjB,OAAO,EAAE,MAAM,EAAE,CAAC;IAClB,UAAU,CAAC,EAAE,MAAM,CAAC;CACrB;;;;;;;;;;;;;;;;;;;GA0BA;AAED,wBAAsB,UAAU,CAC9B,EAAE,EAAE,MAAM,EACV,IAAI,EAAE;IACJ,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,QAAQ,CAAC,EAAE,MAAM,CAAC;IAClB,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,QAAQ,CAAC,EAAE,MAAM,CAAC;IAClB,QAAQ,CAAC,EAAE,OAAO,CAAC;IACnB,OAAO,CAAC,EAAE,MAAM,EAAE,CAAC;IACnB,UAAU,CAAC,EAAE,MAAM,CAAC;IACpB,kBAAkB,CAAC,EAAE,OAAO,CAAC;CAC9B;;;;;;;;;;;;;;;;;;;;;;;;;;;;UAsHF;AA0DD,wBAAsB,UAAU,CAAC,EAAE,EAAE,MAAM;;;;;;;;;;GA6D1C;AAGD,wBAAsB,WAAW;;;;;;;;;;;;;;;;;;;;MAYhC;AAED,wBAAsB,WAAW,CAAC,EAAE,EAAE,MAAM;;;;;;;;;;;;;;;;;WAS3C;AAED,wBAAsB,UAAU,CAAC,IAAI,EAAE;IACrC,IAAI,EAAE,MAAM,CAAC;IACb,WAAW,CAAC,EAAE,MAAM,CAAC;IACrB,aAAa,EAAE,MAAM,EAAE,CAAC;CACzB;;;;;;;;;;;;;;;;;GAeA;AAED,wBAAsB,UAAU,CAC9B,EAAE,EAAE,MAAM,EACV,IAAI,EAAE;IACJ,IAAI,CAAC,EAAE,MAAM,CAAC;IACd,WAAW,CAAC,EAAE,MAAM,CAAC;IACrB,aAAa,CAAC,EAAE,MAAM,EAAE,CAAC;CAC1B;;;;;;;;;;;;;;;;;WAiBF;AAED,wBAAsB,UAAU,CAAC,EAAE,EAAE,MAAM;;;;;;GAU1C;AAGD,wBAAsB,iBAAiB;;;;KAItC"} \ No newline at end of file +{"version":3,"file":"user.service.d.ts","sourceRoot":"","sources":["../../src/services/user.service.ts"],"names":[],"mappings":"AAMA,MAAM,WAAW,WAAW;IAC1B,MAAM,CAAC,EAAE,MAAM,CAAC;IAChB,QAAQ,CAAC,EAAE,OAAO,CAAC;IACnB,MAAM,CAAC,EAAE,MAAM,CAAC;IAChB,IAAI,CAAC,EAAE,MAAM,CAAC;IACd,KAAK,CAAC,EAAE,MAAM,CAAC;CAChB;AAED,wBAAsB,WAAW,CAAC,OAAO,EAAE,WAAW;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GAqErD;AAED,wBAAsB,WAAW,CAAC,EAAE,EAAE,MAAM;;;;;;;;;;;;;;;;;;;;;;;;;;;;UA0C3C;AAED,wBAAsB,UAAU,CAAC,IAAI,EAAE;IACrC,KAAK,EAAE,MAAM,CAAC;IACd,QAAQ,EAAE,MAAM,CAAC;IACjB,SAAS,EAAE,MAAM,CAAC;IAClB,QAAQ,EAAE,MAAM,CAAC;IACjB,OAAO,EAAE,MAAM,EAAE,CAAC;IAClB,UAAU,CAAC,EAAE,MAAM,CAAC;IACpB,kBAAkB,CAAC,EAAE,OAAO,CAAC;CAC9B;;;;;;;;;;;;;;;;;;;GAiCA;AAED,wBAAsB,UAAU,CAC9B,EAAE,EAAE,MAAM,EACV,IAAI,EAAE;IACJ,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,QAAQ,CAAC,EAAE,MAAM,CAAC;IAClB,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,QAAQ,CAAC,EAAE,MAAM,CAAC;IAClB,QAAQ,CAAC,EAAE,OAAO,CAAC;IACnB,OAAO,CAAC,EAAE,MAAM,EAAE,CAAC;IACnB,UAAU,CAAC,EAAE,MAAM,CAAC;IACpB,kBAAkB,CAAC,EAAE,OAAO,CAAC;CAC9B;;;;;;;;;;;;;;;;;;;;;;;;;;;;UAwIF;AAoED,wBAAsB,UAAU,CAAC,EAAE,EAAE,MAAM;;;;;;;;;;;GA6D1C;AAGD,wBAAsB,WAAW;;;;;;;;;;;;;;;;;;;;MAYhC;AAED,wBAAsB,WAAW,CAAC,EAAE,EAAE,MAAM;;;;;;;;;;;;;;;;;WAS3C;AAED,wBAAsB,UAAU,CAAC,IAAI,EAAE;IACrC,IAAI,EAAE,MAAM,CAAC;IACb,WAAW,CAAC,EAAE,MAAM,CAAC;IACrB,aAAa,EAAE,MAAM,EAAE,CAAC;CACzB;;;;;;;;;;;;;;;;;GAeA;AAED,wBAAsB,UAAU,CAC9B,EAAE,EAAE,MAAM,EACV,IAAI,EAAE;IACJ,IAAI,CAAC,EAAE,MAAM,CAAC;IACd,WAAW,CAAC,EAAE,MAAM,CAAC;IACrB,aAAa,CAAC,EAAE,MAAM,EAAE,CAAC;CAC1B;;;;;;;;;;;;;;;;;WAiBF;AAED,wBAAsB,UAAU,CAAC,EAAE,EAAE,MAAM;;;;;;GAU1C;AAGD,wBAAsB,iBAAiB;;;;KAItC"} \ No newline at end of file diff --git a/backend/dist/services/user.service.js b/backend/dist/services/user.service.js index 900c9d69..41f4ecd6 100644 --- a/backend/dist/services/user.service.js +++ b/backend/dist/services/user.service.js @@ -122,7 +122,7 @@ async function getUserById(id) { } async function createUser(data) { const hashedPassword = await bcryptjs_1.default.hash(data.password, 10); - return prisma.user.create({ + const user = await prisma.user.create({ data: { email: data.email, password: hashedPassword, @@ -145,6 +145,11 @@ async function createUser(data) { }, }, }); + // Entwicklerzugriff setzen falls aktiviert + if (data.hasDeveloperAccess) { + await setUserDeveloperAccess(user.id, true); + } + return user; } async function updateUser(id, data) { const { roleIds, password, hasDeveloperAccess, ...userData } = data; @@ -224,10 +229,27 @@ async function updateUser(id, data) { if (password) { userData.password = await bcryptjs_1.default.hash(password, 10); } - // Update user + // Prüfen ob Rollen geändert werden (für Zwangslogout) + let rolesChanged = false; + if (roleIds !== undefined) { + const currentRoles = await prisma.userRole.findMany({ + where: { userId: id }, + select: { roleId: true }, + }); + const currentRoleIds = currentRoles.map((r) => r.roleId).sort(); + const newRoleIds = [...roleIds].sort(); + rolesChanged = + currentRoleIds.length !== newRoleIds.length || + !currentRoleIds.every((id, i) => id === newRoleIds[i]); + } + // Update user - bei Rollenänderung Token invalidieren await prisma.user.update({ where: { id }, - data: userData, + data: { + ...userData, + // Token invalidieren wenn Rollen geändert werden + ...(rolesChanged && { tokenInvalidatedAt: new Date() }), + }, }); // Update roles if provided if (roleIds) { @@ -281,6 +303,11 @@ async function setUserDeveloperAccess(userId, enabled) { await prisma.userRole.create({ data: { userId, roleId: developerRole.id }, }); + // Token invalidieren bei Rechteänderung + await prisma.user.update({ + where: { id: userId }, + data: { tokenInvalidatedAt: new Date() }, + }); } else if (!enabled && hasRole) { // Remove Developer role @@ -288,6 +315,11 @@ async function setUserDeveloperAccess(userId, enabled) { await prisma.userRole.delete({ where: { userId_roleId: { userId, roleId: developerRole.id } }, }); + // Token invalidieren bei Rechteänderung + await prisma.user.update({ + where: { id: userId }, + data: { tokenInvalidatedAt: new Date() }, + }); } else { console.log('No action needed - enabled:', enabled, 'hasRole:', !!hasRole); diff --git a/backend/dist/services/user.service.js.map b/backend/dist/services/user.service.js.map index 52ad90d3..1fc08ce7 100644 --- a/backend/dist/services/user.service.js.map +++ b/backend/dist/services/user.service.js.map @@ -1 +1 @@ -{"version":3,"file":"user.service.js","sourceRoot":"","sources":["../../src/services/user.service.ts"],"names":[],"mappings":"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"} \ No newline at end of file +{"version":3,"file":"user.service.js","sourceRoot":"","sources":["../../src/services/user.service.ts"],"names":[],"mappings":"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"} \ No newline at end of file diff --git a/backend/dist/types/index.d.ts b/backend/dist/types/index.d.ts index 93de078d..790fd7de 100644 --- a/backend/dist/types/index.d.ts +++ b/backend/dist/types/index.d.ts @@ -6,6 +6,7 @@ export interface JwtPayload { customerId?: number; isCustomerPortal?: boolean; representedCustomerIds?: number[]; + iat?: number; } export interface AuthRequest extends Request { user?: JwtPayload; diff --git a/backend/dist/types/index.d.ts.map b/backend/dist/types/index.d.ts.map index c212a70d..5d15fac8 100644 --- a/backend/dist/types/index.d.ts.map +++ b/backend/dist/types/index.d.ts.map @@ -1 +1 @@ -{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/types/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,OAAO,EAAE,MAAM,SAAS,CAAC;AAElC,MAAM,WAAW,UAAU;IACzB,MAAM,CAAC,EAAE,MAAM,CAAC;IAChB,KAAK,EAAE,MAAM,CAAC;IACd,WAAW,EAAE,MAAM,EAAE,CAAC;IACtB,UAAU,CAAC,EAAE,MAAM,CAAC;IACpB,gBAAgB,CAAC,EAAE,OAAO,CAAC;IAC3B,sBAAsB,CAAC,EAAE,MAAM,EAAE,CAAC;CACnC;AAED,MAAM,WAAW,WAAY,SAAQ,OAAO;IAC1C,IAAI,CAAC,EAAE,UAAU,CAAC;CACnB;AAED,MAAM,WAAW,gBAAgB;IAC/B,IAAI,CAAC,EAAE,MAAM,CAAC;IACd,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,MAAM,CAAC,EAAE,MAAM,CAAC;IAChB,SAAS,CAAC,EAAE,KAAK,GAAG,MAAM,CAAC;CAC5B;AAED,MAAM,WAAW,WAAW,CAAC,CAAC,GAAG,OAAO;IACtC,OAAO,EAAE,OAAO,CAAC;IACjB,IAAI,CAAC,EAAE,CAAC,CAAC;IACT,OAAO,CAAC,EAAE,MAAM,CAAC;IACjB,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,UAAU,CAAC,EAAE;QACX,IAAI,EAAE,MAAM,CAAC;QACb,KAAK,EAAE,MAAM,CAAC;QACd,KAAK,EAAE,MAAM,CAAC;QACd,UAAU,EAAE,MAAM,CAAC;KACpB,CAAC;CACH"} \ No newline at end of file +{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/types/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,OAAO,EAAE,MAAM,SAAS,CAAC;AAElC,MAAM,WAAW,UAAU;IACzB,MAAM,CAAC,EAAE,MAAM,CAAC;IAChB,KAAK,EAAE,MAAM,CAAC;IACd,WAAW,EAAE,MAAM,EAAE,CAAC;IACtB,UAAU,CAAC,EAAE,MAAM,CAAC;IACpB,gBAAgB,CAAC,EAAE,OAAO,CAAC;IAC3B,sBAAsB,CAAC,EAAE,MAAM,EAAE,CAAC;IAClC,GAAG,CAAC,EAAE,MAAM,CAAC;CACd;AAED,MAAM,WAAW,WAAY,SAAQ,OAAO;IAC1C,IAAI,CAAC,EAAE,UAAU,CAAC;CACnB;AAED,MAAM,WAAW,gBAAgB;IAC/B,IAAI,CAAC,EAAE,MAAM,CAAC;IACd,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,MAAM,CAAC,EAAE,MAAM,CAAC;IAChB,SAAS,CAAC,EAAE,KAAK,GAAG,MAAM,CAAC;CAC5B;AAED,MAAM,WAAW,WAAW,CAAC,CAAC,GAAG,OAAO;IACtC,OAAO,EAAE,OAAO,CAAC;IACjB,IAAI,CAAC,EAAE,CAAC,CAAC;IACT,OAAO,CAAC,EAAE,MAAM,CAAC;IACjB,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,UAAU,CAAC,EAAE;QACX,IAAI,EAAE,MAAM,CAAC;QACb,KAAK,EAAE,MAAM,CAAC;QACd,KAAK,EAAE,MAAM,CAAC;QACd,UAAU,EAAE,MAAM,CAAC;KACpB,CAAC;CACH"} \ No newline at end of file diff --git a/backend/node_modules/.package-lock.json b/backend/node_modules/.package-lock.json index 6ba6d058..1e0d8190 100644 --- a/backend/node_modules/.package-lock.json +++ b/backend/node_modules/.package-lock.json @@ -20,6 +20,36 @@ "node": ">=18" } }, + "node_modules/@isaacs/cliui": { + "version": "8.0.2", + "resolved": "https://registry.npmjs.org/@isaacs/cliui/-/cliui-8.0.2.tgz", + "integrity": "sha512-O8jcjabXaleOG9DQ0+ARXWZBTfnP4WNAqzuiJK7ll44AmxGKv/J2M4TPjxjY3znBCfvBXFzucm1twdyFybFqEA==", + "dependencies": { + "string-width": "^5.1.2", + "string-width-cjs": "npm:string-width@^4.2.0", + "strip-ansi": "^7.0.1", + "strip-ansi-cjs": "npm:strip-ansi@^6.0.1", + "wrap-ansi": "^8.1.0", + "wrap-ansi-cjs": "npm:wrap-ansi@^7.0.0" + }, + "engines": { + "node": ">=12" + } + }, + "node_modules/@pinojs/redact": { + "version": "0.4.0", + "resolved": "https://registry.npmjs.org/@pinojs/redact/-/redact-0.4.0.tgz", + "integrity": "sha512-k2ENnmBugE/rzQfEcdWHcCY+/FM3VLzH9cYEsbdsoqrvzAKRhUZeRNhAZvB8OitQJ1TBed3yqWtdjzS6wJKBwg==" + }, + "node_modules/@pkgjs/parseargs": { + "version": "0.11.0", + "resolved": "https://registry.npmjs.org/@pkgjs/parseargs/-/parseargs-0.11.0.tgz", + "integrity": "sha512-+1VkjdD0QBLPodGrJUeqarH8VAIvQODIbwh9XpP5Syisf7YoQgsJKPNFoqqLQlu+VQ/tVSshMR6loPMn8U+dPg==", + "optional": true, + "engines": { + "node": ">=14" + } + }, "node_modules/@prisma/client": { "version": "5.22.0", "resolved": "https://registry.npmjs.org/@prisma/client/-/client-5.22.0.tgz", @@ -82,6 +112,36 @@ "@prisma/debug": "5.22.0" } }, + "node_modules/@selderee/plugin-htmlparser2": { + "version": "0.11.0", + "resolved": "https://registry.npmjs.org/@selderee/plugin-htmlparser2/-/plugin-htmlparser2-0.11.0.tgz", + "integrity": "sha512-P33hHGdldxGabLFjPPpaTxVolMrzrcegejx+0GxjrIb9Zv48D8yAIA/QTDR2dFl7Uz7urX8aX6+5bCZslr+gWQ==", + "dependencies": { + "domhandler": "^5.0.3", + "selderee": "^0.11.0" + }, + "funding": { + "url": "https://ko-fi.com/killymxi" + } + }, + "node_modules/@types/adm-zip": { + "version": "0.5.7", + "resolved": "https://registry.npmjs.org/@types/adm-zip/-/adm-zip-0.5.7.tgz", + "integrity": "sha512-DNEs/QvmyRLurdQPChqq0Md4zGvPwHerAJYWk9l2jCbD1VPpnzRJorOdiq4zsw09NFbYnhfsoEhWtxIzXpn2yw==", + "dev": true, + "dependencies": { + "@types/node": "*" + } + }, + "node_modules/@types/archiver": { + "version": "7.0.0", + "resolved": "https://registry.npmjs.org/@types/archiver/-/archiver-7.0.0.tgz", + "integrity": "sha512-/3vwGwx9n+mCQdYZ2IKGGHEFL30I96UgBlk8EtRDDFQ9uxM1l4O5Ci6r00EMAkiDaTqD9DQ6nVrWRICnBPtzzg==", + "dev": true, + "dependencies": { + "@types/readdir-glob": "*" + } + }, "node_modules/@types/bcryptjs": { "version": "2.4.6", "resolved": "https://registry.npmjs.org/@types/bcryptjs/-/bcryptjs-2.4.6.tgz", @@ -156,6 +216,28 @@ "@types/node": "*" } }, + "node_modules/@types/mailparser": { + "version": "3.4.6", + "resolved": "https://registry.npmjs.org/@types/mailparser/-/mailparser-3.4.6.tgz", + "integrity": "sha512-wVV3cnIKzxTffaPH8iRnddX1zahbYB1ZEoAxyhoBo3TBCBuK6nZ8M8JYO/RhsCuuBVOw/DEN/t/ENbruwlxn6Q==", + "dev": true, + "dependencies": { + "@types/node": "*", + "iconv-lite": "^0.6.3" + } + }, + "node_modules/@types/mailparser/node_modules/iconv-lite": { + "version": "0.6.3", + "resolved": "https://registry.npmjs.org/iconv-lite/-/iconv-lite-0.6.3.tgz", + "integrity": "sha512-4fCk79wshMdzMp2rH06qWrJE4iolqLhCUH+OiuIgU++RB0+94NlDL81atO7GX55uUKueo0txHNtvEyI6D7WdMw==", + "dev": true, + "dependencies": { + "safer-buffer": ">= 2.1.2 < 3.0.0" + }, + "engines": { + "node": ">=0.10.0" + } + }, "node_modules/@types/mime": { "version": "1.3.5", "resolved": "https://registry.npmjs.org/@types/mime/-/mime-1.3.5.tgz", @@ -186,6 +268,15 @@ "undici-types": "~6.21.0" } }, + "node_modules/@types/nodemailer": { + "version": "7.0.9", + "resolved": "https://registry.npmjs.org/@types/nodemailer/-/nodemailer-7.0.9.tgz", + "integrity": "sha512-vI8oF1M+8JvQhsId0Pc38BdUP2evenIIys7c7p+9OZXSPOH5c1dyINP1jT8xQ2xPuBUXmIC87s+91IZMDjH8Ow==", + "dev": true, + "dependencies": { + "@types/node": "*" + } + }, "node_modules/@types/qs": { "version": "6.14.0", "resolved": "https://registry.npmjs.org/@types/qs/-/qs-6.14.0.tgz", @@ -198,6 +289,15 @@ "integrity": "sha512-hKormJbkJqzQGhziax5PItDUTMAM9uE2XXQmM37dyd4hVM+5aVl7oVxMVUiVQn2oCQFN/LKCZdvSM0pFRqbSmQ==", "dev": true }, + "node_modules/@types/readdir-glob": { + "version": "1.1.5", + "resolved": "https://registry.npmjs.org/@types/readdir-glob/-/readdir-glob-1.1.5.tgz", + "integrity": "sha512-raiuEPUYqXu+nvtY2Pe8s8FEmZ3x5yAH4VkLdihcPdalvsHltomrRC9BzuStrJ9yk06470hS0Crw0f1pXqD+Hg==", + "dev": true, + "dependencies": { + "@types/node": "*" + } + }, "node_modules/@types/send": { "version": "1.2.1", "resolved": "https://registry.npmjs.org/@types/send/-/send-1.2.1.tgz", @@ -228,6 +328,27 @@ "@types/node": "*" } }, + "node_modules/@zone-eu/mailsplit": { + "version": "5.4.8", + "resolved": "https://registry.npmjs.org/@zone-eu/mailsplit/-/mailsplit-5.4.8.tgz", + "integrity": "sha512-eEyACj4JZ7sjzRvy26QhLgKEMWwQbsw1+QZnlLX+/gihcNH07lVPOcnwf5U6UAL7gkc//J3jVd76o/WS+taUiA==", + "dependencies": { + "libbase64": "1.3.0", + "libmime": "5.3.7", + "libqp": "2.1.1" + } + }, + "node_modules/abort-controller": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/abort-controller/-/abort-controller-3.0.0.tgz", + "integrity": "sha512-h8lQ8tacZYnR3vNQTgibj+tODHI5/+l06Au2Pcriv/Gmet0eaj4TwWH41sO9wnHDiQsEj19q0drzdWdeAHtweg==", + "dependencies": { + "event-target-shim": "^5.0.0" + }, + "engines": { + "node": ">=6.5" + } + }, "node_modules/accepts": { "version": "1.3.8", "resolved": "https://registry.npmjs.org/accepts/-/accepts-1.3.8.tgz", @@ -240,16 +361,189 @@ "node": ">= 0.6" } }, + "node_modules/adm-zip": { + "version": "0.5.16", + "resolved": "https://registry.npmjs.org/adm-zip/-/adm-zip-0.5.16.tgz", + "integrity": "sha512-TGw5yVi4saajsSEgz25grObGHEUaDrniwvA2qwSC060KfqGPdglhvPMA2lPIoxs3PQIItj2iag35fONcQqgUaQ==", + "engines": { + "node": ">=12.0" + } + }, + "node_modules/ansi-regex": { + "version": "6.2.2", + "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-6.2.2.tgz", + "integrity": "sha512-Bq3SmSpyFHaWjPk8If9yc6svM8c56dB5BAtW4Qbw5jHTwwXXcTLoRMkpDJp6VL0XzlWaCHTXrkFURMYmD0sLqg==", + "engines": { + "node": ">=12" + }, + "funding": { + "url": "https://github.com/chalk/ansi-regex?sponsor=1" + } + }, + "node_modules/ansi-styles": { + "version": "6.2.3", + "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-6.2.3.tgz", + "integrity": "sha512-4Dj6M28JB+oAH8kFkTLUo+a2jwOFkuqb3yucU0CANcRRUbxS0cP0nZYCGjcc3BNXwRIsUVmDGgzawme7zvJHvg==", + "engines": { + "node": ">=12" + }, + "funding": { + "url": "https://github.com/chalk/ansi-styles?sponsor=1" + } + }, "node_modules/append-field": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/append-field/-/append-field-1.0.0.tgz", "integrity": "sha512-klpgFSWLW1ZEs8svjfb7g4qWY0YS5imI82dTg+QahUvJ8YqAY0P10Uk8tTyh9ZGuYEZEMaeJYCF5BFuX552hsw==" }, + "node_modules/archiver": { + "version": "7.0.1", + "resolved": "https://registry.npmjs.org/archiver/-/archiver-7.0.1.tgz", + "integrity": "sha512-ZcbTaIqJOfCc03QwD468Unz/5Ir8ATtvAHsK+FdXbDIbGfihqh9mrvdcYunQzqn4HrvWWaFyaxJhGZagaJJpPQ==", + "dependencies": { + "archiver-utils": "^5.0.2", + "async": "^3.2.4", + "buffer-crc32": "^1.0.0", + "readable-stream": "^4.0.0", + "readdir-glob": "^1.1.2", + "tar-stream": "^3.0.0", + "zip-stream": "^6.0.1" + }, + "engines": { + "node": ">= 14" + } + }, + "node_modules/archiver-utils": { + "version": "5.0.2", + "resolved": "https://registry.npmjs.org/archiver-utils/-/archiver-utils-5.0.2.tgz", + "integrity": "sha512-wuLJMmIBQYCsGZgYLTy5FIB2pF6Lfb6cXMSF8Qywwk3t20zWnAi7zLcQFdKQmIB8wyZpY5ER38x08GbwtR2cLA==", + "dependencies": { + "glob": "^10.0.0", + "graceful-fs": "^4.2.0", + "is-stream": "^2.0.1", + "lazystream": "^1.0.0", + "lodash": "^4.17.15", + "normalize-path": "^3.0.0", + "readable-stream": "^4.0.0" + }, + "engines": { + "node": ">= 14" + } + }, + "node_modules/archiver-utils/node_modules/readable-stream": { + "version": "4.7.0", + "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-4.7.0.tgz", + "integrity": "sha512-oIGGmcpTLwPga8Bn6/Z75SVaH1z5dUut2ibSyAMVhmUggWpmDn2dapB0n7f8nwaSiRtepAsfJyfXIO5DCVAODg==", + "dependencies": { + "abort-controller": "^3.0.0", + "buffer": "^6.0.3", + "events": "^3.3.0", + "process": "^0.11.10", + "string_decoder": "^1.3.0" + }, + "engines": { + "node": "^12.22.0 || ^14.17.0 || >=16.0.0" + } + }, + "node_modules/archiver-utils/node_modules/string_decoder": { + "version": "1.3.0", + "resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-1.3.0.tgz", + "integrity": "sha512-hkRX8U1WjJFd8LsDJ2yQ/wWWxaopEsABU1XfkM8A+j0+85JAGppt16cr1Whg6KIbb4okU6Mql6BOj+uup/wKeA==", + "dependencies": { + "safe-buffer": "~5.2.0" + } + }, + "node_modules/archiver/node_modules/readable-stream": { + "version": "4.7.0", + "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-4.7.0.tgz", + "integrity": "sha512-oIGGmcpTLwPga8Bn6/Z75SVaH1z5dUut2ibSyAMVhmUggWpmDn2dapB0n7f8nwaSiRtepAsfJyfXIO5DCVAODg==", + "dependencies": { + "abort-controller": "^3.0.0", + "buffer": "^6.0.3", + "events": "^3.3.0", + "process": "^0.11.10", + "string_decoder": "^1.3.0" + }, + "engines": { + "node": "^12.22.0 || ^14.17.0 || >=16.0.0" + } + }, + "node_modules/archiver/node_modules/string_decoder": { + "version": "1.3.0", + "resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-1.3.0.tgz", + "integrity": "sha512-hkRX8U1WjJFd8LsDJ2yQ/wWWxaopEsABU1XfkM8A+j0+85JAGppt16cr1Whg6KIbb4okU6Mql6BOj+uup/wKeA==", + "dependencies": { + "safe-buffer": "~5.2.0" + } + }, "node_modules/array-flatten": { "version": "1.1.1", "resolved": "https://registry.npmjs.org/array-flatten/-/array-flatten-1.1.1.tgz", "integrity": "sha512-PCVAQswWemu6UdxsDFFX/+gVeYqKAod3D3UVm91jHwynguOwAvYPhx8nNlM++NqRcK6CxxpUafjmhIdKiHibqg==" }, + "node_modules/async": { + "version": "3.2.6", + "resolved": "https://registry.npmjs.org/async/-/async-3.2.6.tgz", + "integrity": "sha512-htCUDlxyyCLMgaM3xXg0C0LW2xqfuQ6p05pCEIsXuyQ+a1koYKTuBMzRNwmybfLgvJDMd0r1LTn4+E0Ti6C2AA==" + }, + "node_modules/atomic-sleep": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/atomic-sleep/-/atomic-sleep-1.0.0.tgz", + "integrity": "sha512-kNOjDqAh7px0XWNI+4QbzoiR/nTkHAWNud2uvnJquD1/x5a7EQZMJT0AczqK0Qn67oY/TTQ1LbUKajZpp3I9tQ==", + "engines": { + "node": ">=8.0.0" + } + }, + "node_modules/b4a": { + "version": "1.7.3", + "resolved": "https://registry.npmjs.org/b4a/-/b4a-1.7.3.tgz", + "integrity": "sha512-5Q2mfq2WfGuFp3uS//0s6baOJLMoVduPYVeNmDYxu5OUA1/cBfvr2RIS7vi62LdNj/urk1hfmj867I3qt6uZ7Q==", + "peerDependencies": { + "react-native-b4a": "*" + }, + "peerDependenciesMeta": { + "react-native-b4a": { + "optional": true + } + } + }, + "node_modules/balanced-match": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/balanced-match/-/balanced-match-1.0.2.tgz", + "integrity": "sha512-3oSeUO0TMV67hN1AmbXsK4yaqU7tjiHlbxRDZOpH0KW9+CeX4bRAaX0Anxt0tx2MrpRpWwQaPwIlISEJhYU5Pw==" + }, + "node_modules/bare-events": { + "version": "2.8.2", + "resolved": "https://registry.npmjs.org/bare-events/-/bare-events-2.8.2.tgz", + "integrity": "sha512-riJjyv1/mHLIPX4RwiK+oW9/4c3TEUeORHKefKAKnZ5kyslbN+HXowtbaVEqt4IMUB7OXlfixcs6gsFeo/jhiQ==", + "peerDependencies": { + "bare-abort-controller": "*" + }, + "peerDependenciesMeta": { + "bare-abort-controller": { + "optional": true + } + } + }, + "node_modules/base64-js": { + "version": "1.5.1", + "resolved": "https://registry.npmjs.org/base64-js/-/base64-js-1.5.1.tgz", + "integrity": "sha512-AKpaYlHn8t4SVbOHCy+b5+KKgvR4vrsD8vbvrbiQJps7fKDTkjkDry6ji0rUJjC0kzbNePLwzxq8iypo41qeWA==", + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/feross" + }, + { + "type": "patreon", + "url": "https://www.patreon.com/feross" + }, + { + "type": "consulting", + "url": "https://feross.org/support" + } + ] + }, "node_modules/bcryptjs": { "version": "2.4.3", "resolved": "https://registry.npmjs.org/bcryptjs/-/bcryptjs-2.4.3.tgz", @@ -278,6 +572,45 @@ "npm": "1.2.8000 || >= 1.4.16" } }, + "node_modules/brace-expansion": { + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-2.0.2.tgz", + "integrity": "sha512-Jt0vHyM+jmUBqojB7E1NIYadt0vI0Qxjxd2TErW94wDz+E2LAm5vKMXXwg6ZZBTHPuUlDgQHKXvjGBdfcF1ZDQ==", + "dependencies": { + "balanced-match": "^1.0.0" + } + }, + "node_modules/buffer": { + "version": "6.0.3", + "resolved": "https://registry.npmjs.org/buffer/-/buffer-6.0.3.tgz", + "integrity": "sha512-FTiCpNxtwiZZHEZbcbTIcZjERVICn9yq/pDFkTl95/AxzD1naBctN7YO68riM/gLSDY7sdrMby8hofADYuuqOA==", + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/feross" + }, + { + "type": "patreon", + "url": "https://www.patreon.com/feross" + }, + { + "type": "consulting", + "url": "https://feross.org/support" + } + ], + "dependencies": { + "base64-js": "^1.3.1", + "ieee754": "^1.2.1" + } + }, + "node_modules/buffer-crc32": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/buffer-crc32/-/buffer-crc32-1.0.0.tgz", + "integrity": "sha512-Db1SbgBS/fg/392AblrMJk97KggmvYhr4pB5ZIMTWtaivCPMWLkmb7m21cJvpvgK+J3nsU2CmmixNBZx4vFj/w==", + "engines": { + "node": ">=8.0.0" + } + }, "node_modules/buffer-equal-constant-time": { "version": "1.0.1", "resolved": "https://registry.npmjs.org/buffer-equal-constant-time/-/buffer-equal-constant-time-1.0.1.tgz", @@ -334,6 +667,60 @@ "url": "https://github.com/sponsors/ljharb" } }, + "node_modules/color-convert": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-2.0.1.tgz", + "integrity": "sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ==", + "dependencies": { + "color-name": "~1.1.4" + }, + "engines": { + "node": ">=7.0.0" + } + }, + "node_modules/color-name": { + "version": "1.1.4", + "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.4.tgz", + "integrity": "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==" + }, + "node_modules/compress-commons": { + "version": "6.0.2", + "resolved": "https://registry.npmjs.org/compress-commons/-/compress-commons-6.0.2.tgz", + "integrity": "sha512-6FqVXeETqWPoGcfzrXb37E50NP0LXT8kAMu5ooZayhWWdgEY4lBEEcbQNXtkuKQsGduxiIcI4gOTsxTmuq/bSg==", + "dependencies": { + "crc-32": "^1.2.0", + "crc32-stream": "^6.0.0", + "is-stream": "^2.0.1", + "normalize-path": "^3.0.0", + "readable-stream": "^4.0.0" + }, + "engines": { + "node": ">= 14" + } + }, + "node_modules/compress-commons/node_modules/readable-stream": { + "version": "4.7.0", + "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-4.7.0.tgz", + "integrity": "sha512-oIGGmcpTLwPga8Bn6/Z75SVaH1z5dUut2ibSyAMVhmUggWpmDn2dapB0n7f8nwaSiRtepAsfJyfXIO5DCVAODg==", + "dependencies": { + "abort-controller": "^3.0.0", + "buffer": "^6.0.3", + "events": "^3.3.0", + "process": "^0.11.10", + "string_decoder": "^1.3.0" + }, + "engines": { + "node": "^12.22.0 || ^14.17.0 || >=16.0.0" + } + }, + "node_modules/compress-commons/node_modules/string_decoder": { + "version": "1.3.0", + "resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-1.3.0.tgz", + "integrity": "sha512-hkRX8U1WjJFd8LsDJ2yQ/wWWxaopEsABU1XfkM8A+j0+85JAGppt16cr1Whg6KIbb4okU6Mql6BOj+uup/wKeA==", + "dependencies": { + "safe-buffer": "~5.2.0" + } + }, "node_modules/concat-stream": { "version": "1.6.2", "resolved": "https://registry.npmjs.org/concat-stream/-/concat-stream-1.6.2.tgz", @@ -397,6 +784,65 @@ "node": ">= 0.10" } }, + "node_modules/crc-32": { + "version": "1.2.2", + "resolved": "https://registry.npmjs.org/crc-32/-/crc-32-1.2.2.tgz", + "integrity": "sha512-ROmzCKrTnOwybPcJApAA6WBWij23HVfGVNKqqrZpuyZOHqK2CwHSvpGuyt/UNNvaIjEd8X5IFGp4Mh+Ie1IHJQ==", + "bin": { + "crc32": "bin/crc32.njs" + }, + "engines": { + "node": ">=0.8" + } + }, + "node_modules/crc32-stream": { + "version": "6.0.0", + "resolved": "https://registry.npmjs.org/crc32-stream/-/crc32-stream-6.0.0.tgz", + "integrity": "sha512-piICUB6ei4IlTv1+653yq5+KoqfBYmj9bw6LqXoOneTMDXk5nM1qt12mFW1caG3LlJXEKW1Bp0WggEmIfQB34g==", + "dependencies": { + "crc-32": "^1.2.0", + "readable-stream": "^4.0.0" + }, + "engines": { + "node": ">= 14" + } + }, + "node_modules/crc32-stream/node_modules/readable-stream": { + "version": "4.7.0", + "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-4.7.0.tgz", + "integrity": "sha512-oIGGmcpTLwPga8Bn6/Z75SVaH1z5dUut2ibSyAMVhmUggWpmDn2dapB0n7f8nwaSiRtepAsfJyfXIO5DCVAODg==", + "dependencies": { + "abort-controller": "^3.0.0", + "buffer": "^6.0.3", + "events": "^3.3.0", + "process": "^0.11.10", + "string_decoder": "^1.3.0" + }, + "engines": { + "node": "^12.22.0 || ^14.17.0 || >=16.0.0" + } + }, + "node_modules/crc32-stream/node_modules/string_decoder": { + "version": "1.3.0", + "resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-1.3.0.tgz", + "integrity": "sha512-hkRX8U1WjJFd8LsDJ2yQ/wWWxaopEsABU1XfkM8A+j0+85JAGppt16cr1Whg6KIbb4okU6Mql6BOj+uup/wKeA==", + "dependencies": { + "safe-buffer": "~5.2.0" + } + }, + "node_modules/cross-spawn": { + "version": "7.0.6", + "resolved": "https://registry.npmjs.org/cross-spawn/-/cross-spawn-7.0.6.tgz", + "integrity": "sha512-uV2QOWP2nWzsy2aMp8aRibhi9dlzF5Hgh5SHaB9OiTGEyDTiJJyx0uy51QXdyWbtAHNua4XJzUKca3OzKUd3vA==", + "dependencies": { + "path-key": "^3.1.0", + "shebang-command": "^2.0.0", + "which": "^2.0.1" + }, + "engines": { + "node": ">= 8" + } + }, "node_modules/debug": { "version": "2.6.9", "resolved": "https://registry.npmjs.org/debug/-/debug-2.6.9.tgz", @@ -405,6 +851,14 @@ "ms": "2.0.0" } }, + "node_modules/deepmerge": { + "version": "4.3.1", + "resolved": "https://registry.npmjs.org/deepmerge/-/deepmerge-4.3.1.tgz", + "integrity": "sha512-3sUqbMEc77XqpdNO7FRyRog+eW3ph+GYCbj+rK+uYyRMuwsVy0rMiVtPn+QJlKFvWP/1PYpapqYn0Me2knFn+A==", + "engines": { + "node": ">=0.10.0" + } + }, "node_modules/depd": { "version": "2.0.0", "resolved": "https://registry.npmjs.org/depd/-/depd-2.0.0.tgz", @@ -422,6 +876,57 @@ "npm": "1.2.8000 || >= 1.4.16" } }, + "node_modules/dom-serializer": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/dom-serializer/-/dom-serializer-2.0.0.tgz", + "integrity": "sha512-wIkAryiqt/nV5EQKqQpo3SToSOV9J0DnbJqwK7Wv/Trc92zIAYZ4FlMu+JPFW1DfGFt81ZTCGgDEabffXeLyJg==", + "dependencies": { + "domelementtype": "^2.3.0", + "domhandler": "^5.0.2", + "entities": "^4.2.0" + }, + "funding": { + "url": "https://github.com/cheeriojs/dom-serializer?sponsor=1" + } + }, + "node_modules/domelementtype": { + "version": "2.3.0", + "resolved": "https://registry.npmjs.org/domelementtype/-/domelementtype-2.3.0.tgz", + "integrity": "sha512-OLETBj6w0OsagBwdXnPdN0cnMfF9opN69co+7ZrbfPGrdpPVNBUj02spi6B1N7wChLQiPn4CSH/zJvXw56gmHw==", + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/fb55" + } + ] + }, + "node_modules/domhandler": { + "version": "5.0.3", + "resolved": "https://registry.npmjs.org/domhandler/-/domhandler-5.0.3.tgz", + "integrity": "sha512-cgwlv/1iFQiFnU96XXgROh8xTeetsnJiDsTc7TYCLFd9+/WNkIqPTxiM/8pSd8VIrhXGTf1Ny1q1hquVqDJB5w==", + "dependencies": { + "domelementtype": "^2.3.0" + }, + "engines": { + "node": ">= 4" + }, + "funding": { + "url": "https://github.com/fb55/domhandler?sponsor=1" + } + }, + "node_modules/domutils": { + "version": "3.2.2", + "resolved": "https://registry.npmjs.org/domutils/-/domutils-3.2.2.tgz", + "integrity": "sha512-6kZKyUajlDuqlHKVX1w7gyslj9MPIXzIFiz/rGu35uC1wMi+kMhQwGhl4lt9unC9Vb9INnY9Z3/ZA3+FhASLaw==", + "dependencies": { + "dom-serializer": "^2.0.0", + "domelementtype": "^2.3.0", + "domhandler": "^5.0.3" + }, + "funding": { + "url": "https://github.com/fb55/domutils?sponsor=1" + } + }, "node_modules/dotenv": { "version": "16.6.1", "resolved": "https://registry.npmjs.org/dotenv/-/dotenv-16.6.1.tgz", @@ -446,6 +951,11 @@ "node": ">= 0.4" } }, + "node_modules/eastasianwidth": { + "version": "0.2.0", + "resolved": "https://registry.npmjs.org/eastasianwidth/-/eastasianwidth-0.2.0.tgz", + "integrity": "sha512-I88TYZWc9XiYHRQ4/3c5rjjfgkjhLyW2luGIheGERbNQ6OY7yTybanSpDXZa8y7VUP9YmDcYa+eyq4ca7iLqWA==" + }, "node_modules/ecdsa-sig-formatter": { "version": "1.0.11", "resolved": "https://registry.npmjs.org/ecdsa-sig-formatter/-/ecdsa-sig-formatter-1.0.11.tgz", @@ -459,6 +969,11 @@ "resolved": "https://registry.npmjs.org/ee-first/-/ee-first-1.1.1.tgz", "integrity": "sha512-WMwm9LhRUo+WUaRN+vRuETqG89IgZphVSNkdFgeb6sS/E4OrDIN7t48CAewSHXc6C8lefD8KKfr5vY61brQlow==" }, + "node_modules/emoji-regex": { + "version": "9.2.2", + "resolved": "https://registry.npmjs.org/emoji-regex/-/emoji-regex-9.2.2.tgz", + "integrity": "sha512-L18DaJsXSUk2+42pv8mLs5jJT2hqFkFE4j21wOmgbUqsZ2hL72NsUU785g9RXgo3s0ZNgVl42TiHp3ZtOv/Vyg==" + }, "node_modules/encodeurl": { "version": "2.0.0", "resolved": "https://registry.npmjs.org/encodeurl/-/encodeurl-2.0.0.tgz", @@ -467,6 +982,25 @@ "node": ">= 0.8" } }, + "node_modules/encoding-japanese": { + "version": "2.2.0", + "resolved": "https://registry.npmjs.org/encoding-japanese/-/encoding-japanese-2.2.0.tgz", + "integrity": "sha512-EuJWwlHPZ1LbADuKTClvHtwbaFn4rOD+dRAbWysqEOXRc2Uui0hJInNJrsdH0c+OhJA4nrCBdSkW4DD5YxAo6A==", + "engines": { + "node": ">=8.10.0" + } + }, + "node_modules/entities": { + "version": "4.5.0", + "resolved": "https://registry.npmjs.org/entities/-/entities-4.5.0.tgz", + "integrity": "sha512-V0hjH4dGPh9Ao5p0MoRY6BVqtwCjhz6vI5LT8AJ55H+4g9/4vbHx1I54fS0XuclLhDHArPQCiMjDxjaL8fPxhw==", + "engines": { + "node": ">=0.12" + }, + "funding": { + "url": "https://github.com/fb55/entities?sponsor=1" + } + }, "node_modules/es-define-property": { "version": "1.0.1", "resolved": "https://registry.npmjs.org/es-define-property/-/es-define-property-1.0.1.tgz", @@ -548,6 +1082,30 @@ "node": ">= 0.6" } }, + "node_modules/event-target-shim": { + "version": "5.0.1", + "resolved": "https://registry.npmjs.org/event-target-shim/-/event-target-shim-5.0.1.tgz", + "integrity": "sha512-i/2XbnSz/uxRCU6+NdVJgKWDTM427+MqYbkQzD321DuCQJUqOuJKIA0IM2+W2xtYHdKOmZ4dR6fExsd4SXL+WQ==", + "engines": { + "node": ">=6" + } + }, + "node_modules/events": { + "version": "3.3.0", + "resolved": "https://registry.npmjs.org/events/-/events-3.3.0.tgz", + "integrity": "sha512-mQw+2fkQbALzQ7V0MY0IqdnXNOeTtP4r0lN9z7AAawCXgqea7bDii20AYrIBrFd/Hx0M2Ocz6S111CaFkUcb0Q==", + "engines": { + "node": ">=0.8.x" + } + }, + "node_modules/events-universal": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/events-universal/-/events-universal-1.0.1.tgz", + "integrity": "sha512-LUd5euvbMLpwOF8m6ivPCbhQeSiYVNb8Vs0fQ8QjXo0JTkEHpz8pxdQf0gStltaPpw0Cca8b39KxvK9cfKRiAw==", + "dependencies": { + "bare-events": "^2.7.0" + } + }, "node_modules/express": { "version": "4.22.1", "resolved": "https://registry.npmjs.org/express/-/express-4.22.1.tgz", @@ -605,6 +1163,11 @@ "node": ">= 8.0.0" } }, + "node_modules/fast-fifo": { + "version": "1.3.2", + "resolved": "https://registry.npmjs.org/fast-fifo/-/fast-fifo-1.3.2.tgz", + "integrity": "sha512-/d9sfos4yxzpwkDkuN7k2SqFKtYNmCTzgfEpz82x34IM9/zc8KGxQoXg1liNC/izpRM/MBdt44Nmx41ZWqk+FQ==" + }, "node_modules/finalhandler": { "version": "1.3.2", "resolved": "https://registry.npmjs.org/finalhandler/-/finalhandler-1.3.2.tgz", @@ -622,6 +1185,21 @@ "node": ">= 0.8" } }, + "node_modules/foreground-child": { + "version": "3.3.1", + "resolved": "https://registry.npmjs.org/foreground-child/-/foreground-child-3.3.1.tgz", + "integrity": "sha512-gIXjKqtFuWEgzFRJA9WCQeSJLZDjgJUOMCMzxtvFq/37KojM1BFGufqsCy0r4qSQmYLsZYMeyRqzIWOMup03sw==", + "dependencies": { + "cross-spawn": "^7.0.6", + "signal-exit": "^4.0.1" + }, + "engines": { + "node": ">=14" + }, + "funding": { + "url": "https://github.com/sponsors/isaacs" + } + }, "node_modules/forwarded": { "version": "0.2.0", "resolved": "https://registry.npmjs.org/forwarded/-/forwarded-0.2.0.tgz", @@ -693,6 +1271,25 @@ "url": "https://github.com/privatenumber/get-tsconfig?sponsor=1" } }, + "node_modules/glob": { + "version": "10.5.0", + "resolved": "https://registry.npmjs.org/glob/-/glob-10.5.0.tgz", + "integrity": "sha512-DfXN8DfhJ7NH3Oe7cFmu3NCu1wKbkReJ8TorzSAFbSKrlNaQSKfIzqYqVY8zlbs2NLBbWpRiU52GX2PbaBVNkg==", + "dependencies": { + "foreground-child": "^3.1.0", + "jackspeak": "^3.1.2", + "minimatch": "^9.0.4", + "minipass": "^7.1.2", + "package-json-from-dist": "^1.0.0", + "path-scurry": "^1.11.1" + }, + "bin": { + "glob": "dist/esm/bin.mjs" + }, + "funding": { + "url": "https://github.com/sponsors/isaacs" + } + }, "node_modules/gopd": { "version": "1.2.0", "resolved": "https://registry.npmjs.org/gopd/-/gopd-1.2.0.tgz", @@ -704,6 +1301,11 @@ "url": "https://github.com/sponsors/ljharb" } }, + "node_modules/graceful-fs": { + "version": "4.2.11", + "resolved": "https://registry.npmjs.org/graceful-fs/-/graceful-fs-4.2.11.tgz", + "integrity": "sha512-RbJ5/jmFcNNCcDV5o9eTnBLJ/HszWV0P73bc+Ff4nS/rJj+YaS6IGyiOL0VoBYX+l1Wrl3k63h/KrH+nhJ0XvQ==" + }, "node_modules/has-symbols": { "version": "1.1.0", "resolved": "https://registry.npmjs.org/has-symbols/-/has-symbols-1.1.0.tgz", @@ -726,6 +1328,47 @@ "node": ">= 0.4" } }, + "node_modules/he": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/he/-/he-1.2.0.tgz", + "integrity": "sha512-F/1DnUGPopORZi0ni+CvrCgHQ5FyEAHRLSApuYWMmrbSwoN2Mn/7k+Gl38gJnR7yyDZk6WLXwiGod1JOWNDKGw==", + "bin": { + "he": "bin/he" + } + }, + "node_modules/html-to-text": { + "version": "9.0.5", + "resolved": "https://registry.npmjs.org/html-to-text/-/html-to-text-9.0.5.tgz", + "integrity": "sha512-qY60FjREgVZL03vJU6IfMV4GDjGBIoOyvuFdpBDIX9yTlDw0TjxVBQp+P8NvpdIXNJvfWBTNul7fsAQJq2FNpg==", + "dependencies": { + "@selderee/plugin-htmlparser2": "^0.11.0", + "deepmerge": "^4.3.1", + "dom-serializer": "^2.0.0", + "htmlparser2": "^8.0.2", + "selderee": "^0.11.0" + }, + "engines": { + "node": ">=14" + } + }, + "node_modules/htmlparser2": { + "version": "8.0.2", + "resolved": "https://registry.npmjs.org/htmlparser2/-/htmlparser2-8.0.2.tgz", + "integrity": "sha512-GYdjWKDkbRLkZ5geuHs5NY1puJ+PXwP7+fHPRz06Eirsb9ugf6d8kkXav6ADhcODhFFPMIXyxkxSuMf3D6NCFA==", + "funding": [ + "https://github.com/fb55/htmlparser2?sponsor=1", + { + "type": "github", + "url": "https://github.com/sponsors/fb55" + } + ], + "dependencies": { + "domelementtype": "^2.3.0", + "domhandler": "^5.0.3", + "domutils": "^3.0.1", + "entities": "^4.4.0" + } + }, "node_modules/http-errors": { "version": "2.0.1", "resolved": "https://registry.npmjs.org/http-errors/-/http-errors-2.0.1.tgz", @@ -756,11 +1399,69 @@ "node": ">=0.10.0" } }, + "node_modules/ieee754": { + "version": "1.2.1", + "resolved": "https://registry.npmjs.org/ieee754/-/ieee754-1.2.1.tgz", + "integrity": "sha512-dcyqhDvX1C46lXZcVqCpK+FtMRQVdIMN6/Df5js2zouUsqG7I6sFxitIC+7KYK29KdXOLHdu9zL4sFnoVQnqaA==", + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/feross" + }, + { + "type": "patreon", + "url": "https://www.patreon.com/feross" + }, + { + "type": "consulting", + "url": "https://feross.org/support" + } + ] + }, + "node_modules/imapflow": { + "version": "1.2.8", + "resolved": "https://registry.npmjs.org/imapflow/-/imapflow-1.2.8.tgz", + "integrity": "sha512-ym7FF2tKOlOzfRvxehs4eLkhjP8Mme3sSp2tcxEbyoeJuJwtEWxaVDv12+DnaMG2LXm0zuQGWZiClq31FLPUNg==", + "dependencies": { + "@zone-eu/mailsplit": "5.4.8", + "encoding-japanese": "2.2.0", + "iconv-lite": "0.7.2", + "libbase64": "1.3.0", + "libmime": "5.3.7", + "libqp": "2.1.1", + "nodemailer": "7.0.13", + "pino": "10.3.0", + "socks": "2.8.7" + } + }, + "node_modules/imapflow/node_modules/iconv-lite": { + "version": "0.7.2", + "resolved": "https://registry.npmjs.org/iconv-lite/-/iconv-lite-0.7.2.tgz", + "integrity": "sha512-im9DjEDQ55s9fL4EYzOAv0yMqmMBSZp6G0VvFyTMPKWxiSBHUj9NW/qqLmXUwXrrM7AvqSlTCfvqRb0cM8yYqw==", + "dependencies": { + "safer-buffer": ">= 2.1.2 < 3.0.0" + }, + "engines": { + "node": ">=0.10.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/express" + } + }, "node_modules/inherits": { "version": "2.0.4", "resolved": "https://registry.npmjs.org/inherits/-/inherits-2.0.4.tgz", "integrity": "sha512-k/vGaX4/Yla3WzyMCvTQOXYeIHvqOKtnqBduzTHpzpQZzAskKMhZ2K+EnBiSM9zGSoIFeMpXKxa4dYeZIQqewQ==" }, + "node_modules/ip-address": { + "version": "10.1.0", + "resolved": "https://registry.npmjs.org/ip-address/-/ip-address-10.1.0.tgz", + "integrity": "sha512-XXADHxXmvT9+CRxhXg56LJovE+bmWnEWB78LB83VZTprKTmaC5QfruXocxzTZ2Kl0DNwKuBdlIhjL8LeY8Sf8Q==", + "engines": { + "node": ">= 12" + } + }, "node_modules/ipaddr.js": { "version": "1.9.1", "resolved": "https://registry.npmjs.org/ipaddr.js/-/ipaddr.js-1.9.1.tgz", @@ -769,11 +1470,49 @@ "node": ">= 0.10" } }, + "node_modules/is-fullwidth-code-point": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/is-fullwidth-code-point/-/is-fullwidth-code-point-3.0.0.tgz", + "integrity": "sha512-zymm5+u+sCsSWyD9qNaejV3DFvhCKclKdizYaJUuHA83RLjb7nSuGnddCHGv0hk+KY7BMAlsWeK4Ueg6EV6XQg==", + "engines": { + "node": ">=8" + } + }, + "node_modules/is-stream": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/is-stream/-/is-stream-2.0.1.tgz", + "integrity": "sha512-hFoiJiTl63nn+kstHGBtewWSKnQLpyb155KHheA1l39uvtO9nWIop1p3udqPcUd/xbF1VLMO4n7OI6p7RbngDg==", + "engines": { + "node": ">=8" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, "node_modules/isarray": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/isarray/-/isarray-1.0.0.tgz", "integrity": "sha512-VLghIWNM6ELQzo7zwmcg0NmTVyWKYjvIeM83yjp0wRDTmUnrM678fQbcKBo6n2CJEF0szoG//ytg+TKla89ALQ==" }, + "node_modules/isexe": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/isexe/-/isexe-2.0.0.tgz", + "integrity": "sha512-RHxMLp9lnKHGHRng9QFhRCMbYAcVpn69smSGcq3f36xjgVVWThj4qqLbTLlq7Ssj8B+fIQ1EuCEGI2lKsyQeIw==" + }, + "node_modules/jackspeak": { + "version": "3.4.3", + "resolved": "https://registry.npmjs.org/jackspeak/-/jackspeak-3.4.3.tgz", + "integrity": "sha512-OGlZQpz2yfahA/Rd1Y8Cd9SIEsqvXkLVoSw/cgwhnhFMDbsQFeZYoJJ7bIZBS9BcamUW96asq/npPWugM+RQBw==", + "dependencies": { + "@isaacs/cliui": "^8.0.2" + }, + "funding": { + "url": "https://github.com/sponsors/isaacs" + }, + "optionalDependencies": { + "@pkgjs/parseargs": "^0.11.0" + } + }, "node_modules/jsonwebtoken": { "version": "9.0.3", "resolved": "https://registry.npmjs.org/jsonwebtoken/-/jsonwebtoken-9.0.3.tgz", @@ -819,6 +1558,65 @@ "safe-buffer": "^5.0.1" } }, + "node_modules/lazystream": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/lazystream/-/lazystream-1.0.1.tgz", + "integrity": "sha512-b94GiNHQNy6JNTrt5w6zNyffMrNkXZb3KTkCZJb2V1xaEGCk093vkZ2jk3tpaeP33/OiXC+WvK9AxUebnf5nbw==", + "dependencies": { + "readable-stream": "^2.0.5" + }, + "engines": { + "node": ">= 0.6.3" + } + }, + "node_modules/leac": { + "version": "0.6.0", + "resolved": "https://registry.npmjs.org/leac/-/leac-0.6.0.tgz", + "integrity": "sha512-y+SqErxb8h7nE/fiEX07jsbuhrpO9lL8eca7/Y1nuWV2moNlXhyd59iDGcRf6moVyDMbmTNzL40SUyrFU/yDpg==", + "funding": { + "url": "https://ko-fi.com/killymxi" + } + }, + "node_modules/libbase64": { + "version": "1.3.0", + "resolved": "https://registry.npmjs.org/libbase64/-/libbase64-1.3.0.tgz", + "integrity": "sha512-GgOXd0Eo6phYgh0DJtjQ2tO8dc0IVINtZJeARPeiIJqge+HdsWSuaDTe8ztQ7j/cONByDZ3zeB325AHiv5O0dg==" + }, + "node_modules/libmime": { + "version": "5.3.7", + "resolved": "https://registry.npmjs.org/libmime/-/libmime-5.3.7.tgz", + "integrity": "sha512-FlDb3Wtha8P01kTL3P9M+ZDNDWPKPmKHWaU/cG/lg5pfuAwdflVpZE+wm9m7pKmC5ww6s+zTxBKS1p6yl3KpSw==", + "dependencies": { + "encoding-japanese": "2.2.0", + "iconv-lite": "0.6.3", + "libbase64": "1.3.0", + "libqp": "2.1.1" + } + }, + "node_modules/libmime/node_modules/iconv-lite": { + "version": "0.6.3", + "resolved": "https://registry.npmjs.org/iconv-lite/-/iconv-lite-0.6.3.tgz", + "integrity": "sha512-4fCk79wshMdzMp2rH06qWrJE4iolqLhCUH+OiuIgU++RB0+94NlDL81atO7GX55uUKueo0txHNtvEyI6D7WdMw==", + "dependencies": { + "safer-buffer": ">= 2.1.2 < 3.0.0" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/libqp": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/libqp/-/libqp-2.1.1.tgz", + "integrity": "sha512-0Wd+GPz1O134cP62YU2GTOPNA7Qgl09XwCqM5zpBv87ERCXdfDtyKXvV7c9U22yWJh44QZqBocFnXN11K96qow==" + }, + "node_modules/linkify-it": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/linkify-it/-/linkify-it-5.0.0.tgz", + "integrity": "sha512-5aHCbzQRADcdP+ATqnDuhhJ/MRIqDkZX5pyjFHRRysS8vZ5AbqGEoFIb6pYHPZ+L/OC2Lc+xT8uHVVR5CAK/wQ==", + "dependencies": { + "uc.micro": "^2.0.0" + } + }, "node_modules/lodash": { "version": "4.17.21", "resolved": "https://registry.npmjs.org/lodash/-/lodash-4.17.21.tgz", @@ -859,6 +1657,43 @@ "resolved": "https://registry.npmjs.org/lodash.once/-/lodash.once-4.1.1.tgz", "integrity": "sha512-Sb487aTOCr9drQVL8pIxOzVhafOjZN9UU54hiN8PU3uAiSV7lx1yYNpbNmex2PK6dSJoNTSJUUswT651yww3Mg==" }, + "node_modules/lru-cache": { + "version": "10.4.3", + "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-10.4.3.tgz", + "integrity": "sha512-JNAzZcXrCt42VGLuYz0zfAzDfAvJWW6AfYlDBQyDV5DClI2m5sAmK+OIO7s59XfsRsWHp02jAJrRadPRGTt6SQ==" + }, + "node_modules/mailparser": { + "version": "3.9.3", + "resolved": "https://registry.npmjs.org/mailparser/-/mailparser-3.9.3.tgz", + "integrity": "sha512-AnB0a3zROum6fLaa52L+/K2SoRJVyFDk78Ea6q1D0ofcZLxWEWDtsS1+OrVqKbV7r5dulKL/AwYQccFGAPpuYQ==", + "dependencies": { + "@zone-eu/mailsplit": "5.4.8", + "encoding-japanese": "2.2.0", + "he": "1.2.0", + "html-to-text": "9.0.5", + "iconv-lite": "0.7.2", + "libmime": "5.3.7", + "linkify-it": "5.0.0", + "nodemailer": "7.0.13", + "punycode.js": "2.3.1", + "tlds": "1.261.0" + } + }, + "node_modules/mailparser/node_modules/iconv-lite": { + "version": "0.7.2", + "resolved": "https://registry.npmjs.org/iconv-lite/-/iconv-lite-0.7.2.tgz", + "integrity": "sha512-im9DjEDQ55s9fL4EYzOAv0yMqmMBSZp6G0VvFyTMPKWxiSBHUj9NW/qqLmXUwXrrM7AvqSlTCfvqRb0cM8yYqw==", + "dependencies": { + "safer-buffer": ">= 2.1.2 < 3.0.0" + }, + "engines": { + "node": ">=0.10.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/express" + } + }, "node_modules/math-intrinsics": { "version": "1.1.0", "resolved": "https://registry.npmjs.org/math-intrinsics/-/math-intrinsics-1.1.0.tgz", @@ -921,6 +1756,20 @@ "node": ">= 0.6" } }, + "node_modules/minimatch": { + "version": "9.0.5", + "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-9.0.5.tgz", + "integrity": "sha512-G6T0ZX48xgozx7587koeX9Ys2NYy6Gmv//P89sEte9V9whIapMNF4idKxnW2QtCcLiTWlb/wfCabAtAFWhhBow==", + "dependencies": { + "brace-expansion": "^2.0.1" + }, + "engines": { + "node": ">=16 || 14 >=14.17" + }, + "funding": { + "url": "https://github.com/sponsors/isaacs" + } + }, "node_modules/minimist": { "version": "1.2.8", "resolved": "https://registry.npmjs.org/minimist/-/minimist-1.2.8.tgz", @@ -929,6 +1778,14 @@ "url": "https://github.com/sponsors/ljharb" } }, + "node_modules/minipass": { + "version": "7.1.2", + "resolved": "https://registry.npmjs.org/minipass/-/minipass-7.1.2.tgz", + "integrity": "sha512-qOOzS1cBTWYF4BH8fVePDBOO9iptMnGUEZwNc/cMWnTV2nVLZ7VoNWEPHkYczZA0pdoA7dl6e7FL659nX9S2aw==", + "engines": { + "node": ">=16 || 14 >=14.17" + } + }, "node_modules/mkdirp": { "version": "0.5.6", "resolved": "https://registry.npmjs.org/mkdirp/-/mkdirp-0.5.6.tgz", @@ -971,6 +1828,22 @@ "node": ">= 0.6" } }, + "node_modules/nodemailer": { + "version": "7.0.13", + "resolved": "https://registry.npmjs.org/nodemailer/-/nodemailer-7.0.13.tgz", + "integrity": "sha512-PNDFSJdP+KFgdsG3ZzMXCgquO7I6McjY2vlqILjtJd0hy8wEvtugS9xKRF2NWlPNGxvLCXlTNIae4serI7dinw==", + "engines": { + "node": ">=6.0.0" + } + }, + "node_modules/normalize-path": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/normalize-path/-/normalize-path-3.0.0.tgz", + "integrity": "sha512-6eZs5Ls3WtCisHWp9S2GUy8dqkpGi4BVSz3GaqiE6ezub0512ESztXUwUB6C6IKbQkY2Pnb/mD4WYojCRwcwLA==", + "engines": { + "node": ">=0.10.0" + } + }, "node_modules/object-assign": { "version": "4.1.1", "resolved": "https://registry.npmjs.org/object-assign/-/object-assign-4.1.1.tgz", @@ -990,6 +1863,14 @@ "url": "https://github.com/sponsors/ljharb" } }, + "node_modules/on-exit-leak-free": { + "version": "2.1.2", + "resolved": "https://registry.npmjs.org/on-exit-leak-free/-/on-exit-leak-free-2.1.2.tgz", + "integrity": "sha512-0eJJY6hXLGf1udHwfNftBqH+g73EU4B504nZeKpz1sYRKafAghwxEJunB2O7rDZkL4PGfsMVnTXZ2EjibbqcsA==", + "engines": { + "node": ">=14.0.0" + } + }, "node_modules/on-finished": { "version": "2.4.1", "resolved": "https://registry.npmjs.org/on-finished/-/on-finished-2.4.1.tgz", @@ -1001,6 +1882,23 @@ "node": ">= 0.8" } }, + "node_modules/package-json-from-dist": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/package-json-from-dist/-/package-json-from-dist-1.0.1.tgz", + "integrity": "sha512-UEZIS3/by4OC8vL3P2dTXRETpebLI2NiI5vIrjaD/5UtrkFX/tNbwjTSRAGC/+7CAo2pIcBaRgWmcBBHcsaCIw==" + }, + "node_modules/parseley": { + "version": "0.12.1", + "resolved": "https://registry.npmjs.org/parseley/-/parseley-0.12.1.tgz", + "integrity": "sha512-e6qHKe3a9HWr0oMRVDTRhKce+bRO8VGQR3NyVwcjwrbhMmFCX9KszEV35+rn4AdilFAq9VPxP/Fe1wC9Qjd2lw==", + "dependencies": { + "leac": "^0.6.0", + "peberminta": "^0.9.0" + }, + "funding": { + "url": "https://ko-fi.com/killymxi" + } + }, "node_modules/parseurl": { "version": "1.3.3", "resolved": "https://registry.npmjs.org/parseurl/-/parseurl-1.3.3.tgz", @@ -1009,11 +1907,76 @@ "node": ">= 0.8" } }, + "node_modules/path-key": { + "version": "3.1.1", + "resolved": "https://registry.npmjs.org/path-key/-/path-key-3.1.1.tgz", + "integrity": "sha512-ojmeN0qd+y0jszEtoY48r0Peq5dwMEkIlCOu6Q5f41lfkswXuKtYrhgoTpLnyIcHm24Uhqx+5Tqm2InSwLhE6Q==", + "engines": { + "node": ">=8" + } + }, + "node_modules/path-scurry": { + "version": "1.11.1", + "resolved": "https://registry.npmjs.org/path-scurry/-/path-scurry-1.11.1.tgz", + "integrity": "sha512-Xa4Nw17FS9ApQFJ9umLiJS4orGjm7ZzwUrwamcGQuHSzDyth9boKDaycYdDcZDuqYATXw4HFXgaqWTctW/v1HA==", + "dependencies": { + "lru-cache": "^10.2.0", + "minipass": "^5.0.0 || ^6.0.2 || ^7.0.0" + }, + "engines": { + "node": ">=16 || 14 >=14.18" + }, + "funding": { + "url": "https://github.com/sponsors/isaacs" + } + }, "node_modules/path-to-regexp": { "version": "0.1.12", "resolved": "https://registry.npmjs.org/path-to-regexp/-/path-to-regexp-0.1.12.tgz", "integrity": "sha512-RA1GjUVMnvYFxuqovrEqZoxxW5NUZqbwKtYz/Tt7nXerk0LbLblQmrsgdeOxV5SFHf0UDggjS/bSeOZwt1pmEQ==" }, + "node_modules/peberminta": { + "version": "0.9.0", + "resolved": "https://registry.npmjs.org/peberminta/-/peberminta-0.9.0.tgz", + "integrity": "sha512-XIxfHpEuSJbITd1H3EeQwpcZbTLHc+VVr8ANI9t5sit565tsI4/xK3KWTUFE2e6QiangUkh3B0jihzmGnNrRsQ==", + "funding": { + "url": "https://ko-fi.com/killymxi" + } + }, + "node_modules/pino": { + "version": "10.3.0", + "resolved": "https://registry.npmjs.org/pino/-/pino-10.3.0.tgz", + "integrity": "sha512-0GNPNzHXBKw6U/InGe79A3Crzyk9bcSyObF9/Gfo9DLEf5qj5RF50RSjsu0W1rZ6ZqRGdzDFCRBQvi9/rSGPtA==", + "dependencies": { + "@pinojs/redact": "^0.4.0", + "atomic-sleep": "^1.0.0", + "on-exit-leak-free": "^2.1.0", + "pino-abstract-transport": "^3.0.0", + "pino-std-serializers": "^7.0.0", + "process-warning": "^5.0.0", + "quick-format-unescaped": "^4.0.3", + "real-require": "^0.2.0", + "safe-stable-stringify": "^2.3.1", + "sonic-boom": "^4.0.1", + "thread-stream": "^4.0.0" + }, + "bin": { + "pino": "bin.js" + } + }, + "node_modules/pino-abstract-transport": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/pino-abstract-transport/-/pino-abstract-transport-3.0.0.tgz", + "integrity": "sha512-wlfUczU+n7Hy/Ha5j9a/gZNy7We5+cXp8YL+X+PG8S0KXxw7n/JXA3c46Y0zQznIJ83URJiwy7Lh56WLokNuxg==", + "dependencies": { + "split2": "^4.0.0" + } + }, + "node_modules/pino-std-serializers": { + "version": "7.1.0", + "resolved": "https://registry.npmjs.org/pino-std-serializers/-/pino-std-serializers-7.1.0.tgz", + "integrity": "sha512-BndPH67/JxGExRgiX1dX0w1FvZck5Wa4aal9198SrRhZjH3GxKQUKIBnYJTdj2HDN3UQAS06HlfcSbQj2OHmaw==" + }, "node_modules/prisma": { "version": "5.22.0", "resolved": "https://registry.npmjs.org/prisma/-/prisma-5.22.0.tgz", @@ -1033,11 +1996,34 @@ "fsevents": "2.3.3" } }, + "node_modules/process": { + "version": "0.11.10", + "resolved": "https://registry.npmjs.org/process/-/process-0.11.10.tgz", + "integrity": "sha512-cdGef/drWFoydD1JsMzuFf8100nZl+GT+yacc2bEced5f9Rjk4z+WtFUTBu9PhOi9j/jfmBPu0mMEY4wIdAF8A==", + "engines": { + "node": ">= 0.6.0" + } + }, "node_modules/process-nextick-args": { "version": "2.0.1", "resolved": "https://registry.npmjs.org/process-nextick-args/-/process-nextick-args-2.0.1.tgz", "integrity": "sha512-3ouUOpQhtgrbOa17J7+uxOTpITYWaGP7/AhoR3+A+/1e9skrzelGi/dXzEYyvbxubEF6Wn2ypscTKiKJFFn1ag==" }, + "node_modules/process-warning": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/process-warning/-/process-warning-5.0.0.tgz", + "integrity": "sha512-a39t9ApHNx2L4+HBnQKqxxHNs1r7KF+Intd8Q/g1bUh6q0WIp9voPXJ/x0j+ZL45KF1pJd9+q2jLIRMfvEshkA==", + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/fastify" + }, + { + "type": "opencollective", + "url": "https://opencollective.com/fastify" + } + ] + }, "node_modules/proxy-addr": { "version": "2.0.7", "resolved": "https://registry.npmjs.org/proxy-addr/-/proxy-addr-2.0.7.tgz", @@ -1050,6 +2036,14 @@ "node": ">= 0.10" } }, + "node_modules/punycode.js": { + "version": "2.3.1", + "resolved": "https://registry.npmjs.org/punycode.js/-/punycode.js-2.3.1.tgz", + "integrity": "sha512-uxFIHU0YlHYhDQtV4R9J6a52SLx28BCjT+4ieh7IGbgwVJWO+km431c4yRlREUAsAmt/uMjQUyQHNEPf0M39CA==", + "engines": { + "node": ">=6" + } + }, "node_modules/qs": { "version": "6.14.1", "resolved": "https://registry.npmjs.org/qs/-/qs-6.14.1.tgz", @@ -1064,6 +2058,11 @@ "url": "https://github.com/sponsors/ljharb" } }, + "node_modules/quick-format-unescaped": { + "version": "4.0.4", + "resolved": "https://registry.npmjs.org/quick-format-unescaped/-/quick-format-unescaped-4.0.4.tgz", + "integrity": "sha512-tYC1Q1hgyRuHgloV/YXs2w15unPVh8qfu/qCTfhTYamaw7fyhumKa2yGpdSo87vY32rIclj+4fWYQXUMs9EHvg==" + }, "node_modules/range-parser": { "version": "1.2.1", "resolved": "https://registry.npmjs.org/range-parser/-/range-parser-1.2.1.tgz", @@ -1105,6 +2104,33 @@ "resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.1.2.tgz", "integrity": "sha512-Gd2UZBJDkXlY7GbJxfsE8/nvKkUEU1G38c1siN6QP6a9PT9MmHB8GnpscSmMJSoF8LOIrt8ud/wPtojys4G6+g==" }, + "node_modules/readdir-glob": { + "version": "1.1.3", + "resolved": "https://registry.npmjs.org/readdir-glob/-/readdir-glob-1.1.3.tgz", + "integrity": "sha512-v05I2k7xN8zXvPD9N+z/uhXPaj0sUFCe2rcWZIpBsqxfP7xXFQ0tipAd/wjj1YxWyWtUS5IDJpOG82JKt2EAVA==", + "dependencies": { + "minimatch": "^5.1.0" + } + }, + "node_modules/readdir-glob/node_modules/minimatch": { + "version": "5.1.6", + "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-5.1.6.tgz", + "integrity": "sha512-lKwV/1brpG6mBUFHtb7NUmtABCb2WZZmm2wNiOA5hAb8VdCS4B3dtMWyvcoViccwAW/COERjXLt0zP1zXUN26g==", + "dependencies": { + "brace-expansion": "^2.0.1" + }, + "engines": { + "node": ">=10" + } + }, + "node_modules/real-require": { + "version": "0.2.0", + "resolved": "https://registry.npmjs.org/real-require/-/real-require-0.2.0.tgz", + "integrity": "sha512-57frrGM/OCTLqLOAh0mhVA9VBMHd+9U7Zb2THMGdBUoZVOtGbJzjxsYGDJ3A9AYYCP4hn6y1TVbaOfzWtm5GFg==", + "engines": { + "node": ">= 12.13.0" + } + }, "node_modules/resolve-pkg-maps": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/resolve-pkg-maps/-/resolve-pkg-maps-1.0.0.tgz", @@ -1133,11 +2159,30 @@ } ] }, + "node_modules/safe-stable-stringify": { + "version": "2.5.0", + "resolved": "https://registry.npmjs.org/safe-stable-stringify/-/safe-stable-stringify-2.5.0.tgz", + "integrity": "sha512-b3rppTKm9T+PsVCBEOUR46GWI7fdOs00VKZ1+9c1EWDaDMvjQc6tUwuFyIprgGgTcWoVHSKrU8H31ZHA2e0RHA==", + "engines": { + "node": ">=10" + } + }, "node_modules/safer-buffer": { "version": "2.1.2", "resolved": "https://registry.npmjs.org/safer-buffer/-/safer-buffer-2.1.2.tgz", "integrity": "sha512-YZo3K82SD7Riyi0E1EQPojLz7kpepnSQI9IyPbHHg1XXXevb5dJI7tpyN2ADxGcQbHG7vcyRHk0cbwqcQriUtg==" }, + "node_modules/selderee": { + "version": "0.11.0", + "resolved": "https://registry.npmjs.org/selderee/-/selderee-0.11.0.tgz", + "integrity": "sha512-5TF+l7p4+OsnP8BCCvSyZiSPc4x4//p5uPwK8TCnVPJYRmU2aYKMpOXvw8zM5a5JvuuCGN1jmsMwuU2W02ukfA==", + "dependencies": { + "parseley": "^0.12.0" + }, + "funding": { + "url": "https://ko-fi.com/killymxi" + } + }, "node_modules/semver": { "version": "7.7.3", "resolved": "https://registry.npmjs.org/semver/-/semver-7.7.3.tgz", @@ -1196,6 +2241,25 @@ "resolved": "https://registry.npmjs.org/setprototypeof/-/setprototypeof-1.2.0.tgz", "integrity": "sha512-E5LDX7Wrp85Kil5bhZv46j8jOeboKq5JMmYM3gVGdGH8xFpPWXUMsNrlODCrkoxMEeNi/XZIwuRvY4XNwYMJpw==" }, + "node_modules/shebang-command": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/shebang-command/-/shebang-command-2.0.0.tgz", + "integrity": "sha512-kHxr2zZpYtdmrN1qDjrrX/Z1rR1kG8Dx+gkpK1G4eXmvXswmcE1hTWBWYUzlraYw1/yZp6YuDY77YtvbN0dmDA==", + "dependencies": { + "shebang-regex": "^3.0.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/shebang-regex": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/shebang-regex/-/shebang-regex-3.0.0.tgz", + "integrity": "sha512-7++dFhtcx3353uBaq8DDR4NuxBetBzC7ZQOhmTQInHEd6bSrXdiEyzCvG07Z44UYdLShWUyXt5M/yhz8ekcb1A==", + "engines": { + "node": ">=8" + } + }, "node_modules/side-channel": { "version": "1.1.0", "resolved": "https://registry.npmjs.org/side-channel/-/side-channel-1.1.0.tgz", @@ -1264,6 +2328,55 @@ "url": "https://github.com/sponsors/ljharb" } }, + "node_modules/signal-exit": { + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/signal-exit/-/signal-exit-4.1.0.tgz", + "integrity": "sha512-bzyZ1e88w9O1iNJbKnOlvYTrWPDl46O1bG0D3XInv+9tkPrxrN8jUUTiFlDkkmKWgn1M6CfIA13SuGqOa9Korw==", + "engines": { + "node": ">=14" + }, + "funding": { + "url": "https://github.com/sponsors/isaacs" + } + }, + "node_modules/smart-buffer": { + "version": "4.2.0", + "resolved": "https://registry.npmjs.org/smart-buffer/-/smart-buffer-4.2.0.tgz", + "integrity": "sha512-94hK0Hh8rPqQl2xXc3HsaBoOXKV20MToPkcXvwbISWLEs+64sBq5kFgn2kJDHb1Pry9yrP0dxrCI9RRci7RXKg==", + "engines": { + "node": ">= 6.0.0", + "npm": ">= 3.0.0" + } + }, + "node_modules/socks": { + "version": "2.8.7", + "resolved": "https://registry.npmjs.org/socks/-/socks-2.8.7.tgz", + "integrity": "sha512-HLpt+uLy/pxB+bum/9DzAgiKS8CX1EvbWxI4zlmgGCExImLdiad2iCwXT5Z4c9c3Eq8rP2318mPW2c+QbtjK8A==", + "dependencies": { + "ip-address": "^10.0.1", + "smart-buffer": "^4.2.0" + }, + "engines": { + "node": ">= 10.0.0", + "npm": ">= 3.0.0" + } + }, + "node_modules/sonic-boom": { + "version": "4.2.0", + "resolved": "https://registry.npmjs.org/sonic-boom/-/sonic-boom-4.2.0.tgz", + "integrity": "sha512-INb7TM37/mAcsGmc9hyyI6+QR3rR1zVRu36B0NeGXKnOOLiZOfER5SA+N7X7k3yUYRzLWafduTDvJAfDswwEww==", + "dependencies": { + "atomic-sleep": "^1.0.0" + } + }, + "node_modules/split2": { + "version": "4.2.0", + "resolved": "https://registry.npmjs.org/split2/-/split2-4.2.0.tgz", + "integrity": "sha512-UcjcJOWknrNkF6PLX83qcHM6KHgVKNkV62Y8a5uYDVv9ydGQVwAHMKqHdJje1VTWpljG0WYpCDhrCdAOYH4TWg==", + "engines": { + "node": ">= 10.x" + } + }, "node_modules/statuses": { "version": "2.0.2", "resolved": "https://registry.npmjs.org/statuses/-/statuses-2.0.2.tgz", @@ -1280,6 +2393,16 @@ "node": ">=10.0.0" } }, + "node_modules/streamx": { + "version": "2.23.0", + "resolved": "https://registry.npmjs.org/streamx/-/streamx-2.23.0.tgz", + "integrity": "sha512-kn+e44esVfn2Fa/O0CPFcex27fjIL6MkVae0Mm6q+E6f0hWv578YCERbv+4m02cjxvDsPKLnmxral/rR6lBMAg==", + "dependencies": { + "events-universal": "^1.0.0", + "fast-fifo": "^1.3.2", + "text-decoder": "^1.1.0" + } + }, "node_modules/string_decoder": { "version": "1.1.1", "resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-1.1.1.tgz", @@ -1293,6 +2416,131 @@ "resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.1.2.tgz", "integrity": "sha512-Gd2UZBJDkXlY7GbJxfsE8/nvKkUEU1G38c1siN6QP6a9PT9MmHB8GnpscSmMJSoF8LOIrt8ud/wPtojys4G6+g==" }, + "node_modules/string-width": { + "version": "5.1.2", + "resolved": "https://registry.npmjs.org/string-width/-/string-width-5.1.2.tgz", + "integrity": "sha512-HnLOCR3vjcY8beoNLtcjZ5/nxn2afmME6lhrDrebokqMap+XbeW8n9TXpPDOqdGK5qcI3oT0GKTW6wC7EMiVqA==", + "dependencies": { + "eastasianwidth": "^0.2.0", + "emoji-regex": "^9.2.2", + "strip-ansi": "^7.0.1" + }, + "engines": { + "node": ">=12" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/string-width-cjs": { + "name": "string-width", + "version": "4.2.3", + "resolved": "https://registry.npmjs.org/string-width/-/string-width-4.2.3.tgz", + "integrity": "sha512-wKyQRQpjJ0sIp62ErSZdGsjMJWsap5oRNihHhu6G7JVO/9jIB6UyevL+tXuOqrng8j/cxKTWyWUwvSTriiZz/g==", + "dependencies": { + "emoji-regex": "^8.0.0", + "is-fullwidth-code-point": "^3.0.0", + "strip-ansi": "^6.0.1" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/string-width-cjs/node_modules/ansi-regex": { + "version": "5.0.1", + "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-5.0.1.tgz", + "integrity": "sha512-quJQXlTSUGL2LH9SUXo8VwsY4soanhgo6LNSm84E1LBcE8s3O0wpdiRzyR9z/ZZJMlMWv37qOOb9pdJlMUEKFQ==", + "engines": { + "node": ">=8" + } + }, + "node_modules/string-width-cjs/node_modules/emoji-regex": { + "version": "8.0.0", + "resolved": "https://registry.npmjs.org/emoji-regex/-/emoji-regex-8.0.0.tgz", + "integrity": "sha512-MSjYzcWNOA0ewAHpz0MxpYFvwg6yjy1NG3xteoqz644VCo/RPgnr1/GGt+ic3iJTzQ8Eu3TdM14SawnVUmGE6A==" + }, + "node_modules/string-width-cjs/node_modules/strip-ansi": { + "version": "6.0.1", + "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-6.0.1.tgz", + "integrity": "sha512-Y38VPSHcqkFrCpFnQ9vuSXmquuv5oXOKpGeT6aGrr3o3Gc9AlVa6JBfUSOCnbxGGZF+/0ooI7KrPuUSztUdU5A==", + "dependencies": { + "ansi-regex": "^5.0.1" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/strip-ansi": { + "version": "7.1.2", + "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-7.1.2.tgz", + "integrity": "sha512-gmBGslpoQJtgnMAvOVqGZpEz9dyoKTCzy2nfz/n8aIFhN/jCE/rCmcxabB6jOOHV+0WNnylOxaxBQPSvcWklhA==", + "dependencies": { + "ansi-regex": "^6.0.1" + }, + "engines": { + "node": ">=12" + }, + "funding": { + "url": "https://github.com/chalk/strip-ansi?sponsor=1" + } + }, + "node_modules/strip-ansi-cjs": { + "name": "strip-ansi", + "version": "6.0.1", + "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-6.0.1.tgz", + "integrity": "sha512-Y38VPSHcqkFrCpFnQ9vuSXmquuv5oXOKpGeT6aGrr3o3Gc9AlVa6JBfUSOCnbxGGZF+/0ooI7KrPuUSztUdU5A==", + "dependencies": { + "ansi-regex": "^5.0.1" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/strip-ansi-cjs/node_modules/ansi-regex": { + "version": "5.0.1", + "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-5.0.1.tgz", + "integrity": "sha512-quJQXlTSUGL2LH9SUXo8VwsY4soanhgo6LNSm84E1LBcE8s3O0wpdiRzyR9z/ZZJMlMWv37qOOb9pdJlMUEKFQ==", + "engines": { + "node": ">=8" + } + }, + "node_modules/tar-stream": { + "version": "3.1.7", + "resolved": "https://registry.npmjs.org/tar-stream/-/tar-stream-3.1.7.tgz", + "integrity": "sha512-qJj60CXt7IU1Ffyc3NJMjh6EkuCFej46zUqJ4J7pqYlThyd9bO0XBTmcOIhSzZJVWfsLks0+nle/j538YAW9RQ==", + "dependencies": { + "b4a": "^1.6.4", + "fast-fifo": "^1.2.0", + "streamx": "^2.15.0" + } + }, + "node_modules/text-decoder": { + "version": "1.2.3", + "resolved": "https://registry.npmjs.org/text-decoder/-/text-decoder-1.2.3.tgz", + "integrity": "sha512-3/o9z3X0X0fTupwsYvR03pJ/DjWuqqrfwBgTQzdWDiQSm9KitAyz/9WqsT2JQW7KV2m+bC2ol/zqpW37NHxLaA==", + "dependencies": { + "b4a": "^1.6.4" + } + }, + "node_modules/thread-stream": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/thread-stream/-/thread-stream-4.0.0.tgz", + "integrity": "sha512-4iMVL6HAINXWf1ZKZjIPcz5wYaOdPhtO8ATvZ+Xqp3BTdaqtAwQkNmKORqcIo5YkQqGXq5cwfswDwMqqQNrpJA==", + "dependencies": { + "real-require": "^0.2.0" + }, + "engines": { + "node": ">=20" + } + }, + "node_modules/tlds": { + "version": "1.261.0", + "resolved": "https://registry.npmjs.org/tlds/-/tlds-1.261.0.tgz", + "integrity": "sha512-QXqwfEl9ddlGBaRFXIvNKK6OhipSiLXuRuLJX5DErz0o0Q0rYxulWLdFryTkV5PkdZct5iMInwYEGe/eR++1AA==", + "bin": { + "tlds": "bin.js" + } + }, "node_modules/toidentifier": { "version": "1.0.1", "resolved": "https://registry.npmjs.org/toidentifier/-/toidentifier-1.0.1.tgz", @@ -1350,6 +2598,11 @@ "node": ">=14.17" } }, + "node_modules/uc.micro": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/uc.micro/-/uc.micro-2.1.0.tgz", + "integrity": "sha512-ARDJmphmdvUk6Glw7y9DQ2bFkKBHwQHLi2lsaH6PPmz/Ka9sFOBsBluozhDltWmnv9u/cF6Rt87znRTPV+yp/A==" + }, "node_modules/undici": { "version": "6.23.0", "resolved": "https://registry.npmjs.org/undici/-/undici-6.23.0.tgz", @@ -1401,6 +2654,104 @@ "node": ">= 0.8" } }, + "node_modules/which": { + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/which/-/which-2.0.2.tgz", + "integrity": "sha512-BLI3Tl1TW3Pvl70l3yq3Y64i+awpwXqsGBYWkkqMtnbXgrMD+yj7rhW0kuEDxzJaYXGjEW5ogapKNMEKNMjibA==", + "dependencies": { + "isexe": "^2.0.0" + }, + "bin": { + "node-which": "bin/node-which" + }, + "engines": { + "node": ">= 8" + } + }, + "node_modules/wrap-ansi": { + "version": "8.1.0", + "resolved": "https://registry.npmjs.org/wrap-ansi/-/wrap-ansi-8.1.0.tgz", + "integrity": "sha512-si7QWI6zUMq56bESFvagtmzMdGOtoxfR+Sez11Mobfc7tm+VkUckk9bW2UeffTGVUbOksxmSw0AA2gs8g71NCQ==", + "dependencies": { + "ansi-styles": "^6.1.0", + "string-width": "^5.0.1", + "strip-ansi": "^7.0.1" + }, + "engines": { + "node": ">=12" + }, + "funding": { + "url": "https://github.com/chalk/wrap-ansi?sponsor=1" + } + }, + "node_modules/wrap-ansi-cjs": { + "name": "wrap-ansi", + "version": "7.0.0", + "resolved": "https://registry.npmjs.org/wrap-ansi/-/wrap-ansi-7.0.0.tgz", + "integrity": "sha512-YVGIj2kamLSTxw6NsZjoBxfSwsn0ycdesmc4p+Q21c5zPuZ1pl+NfxVdxPtdHvmNVOQ6XSYG4AUtyt/Fi7D16Q==", + "dependencies": { + "ansi-styles": "^4.0.0", + "string-width": "^4.1.0", + "strip-ansi": "^6.0.0" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/chalk/wrap-ansi?sponsor=1" + } + }, + "node_modules/wrap-ansi-cjs/node_modules/ansi-regex": { + "version": "5.0.1", + "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-5.0.1.tgz", + "integrity": "sha512-quJQXlTSUGL2LH9SUXo8VwsY4soanhgo6LNSm84E1LBcE8s3O0wpdiRzyR9z/ZZJMlMWv37qOOb9pdJlMUEKFQ==", + "engines": { + "node": ">=8" + } + }, + "node_modules/wrap-ansi-cjs/node_modules/ansi-styles": { + "version": "4.3.0", + "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.3.0.tgz", + "integrity": "sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==", + "dependencies": { + "color-convert": "^2.0.1" + }, + "engines": { + "node": ">=8" + }, + "funding": { + "url": "https://github.com/chalk/ansi-styles?sponsor=1" + } + }, + "node_modules/wrap-ansi-cjs/node_modules/emoji-regex": { + "version": "8.0.0", + "resolved": "https://registry.npmjs.org/emoji-regex/-/emoji-regex-8.0.0.tgz", + "integrity": "sha512-MSjYzcWNOA0ewAHpz0MxpYFvwg6yjy1NG3xteoqz644VCo/RPgnr1/GGt+ic3iJTzQ8Eu3TdM14SawnVUmGE6A==" + }, + "node_modules/wrap-ansi-cjs/node_modules/string-width": { + "version": "4.2.3", + "resolved": "https://registry.npmjs.org/string-width/-/string-width-4.2.3.tgz", + "integrity": "sha512-wKyQRQpjJ0sIp62ErSZdGsjMJWsap5oRNihHhu6G7JVO/9jIB6UyevL+tXuOqrng8j/cxKTWyWUwvSTriiZz/g==", + "dependencies": { + "emoji-regex": "^8.0.0", + "is-fullwidth-code-point": "^3.0.0", + "strip-ansi": "^6.0.1" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/wrap-ansi-cjs/node_modules/strip-ansi": { + "version": "6.0.1", + "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-6.0.1.tgz", + "integrity": "sha512-Y38VPSHcqkFrCpFnQ9vuSXmquuv5oXOKpGeT6aGrr3o3Gc9AlVa6JBfUSOCnbxGGZF+/0ooI7KrPuUSztUdU5A==", + "dependencies": { + "ansi-regex": "^5.0.1" + }, + "engines": { + "node": ">=8" + } + }, "node_modules/xtend": { "version": "4.0.2", "resolved": "https://registry.npmjs.org/xtend/-/xtend-4.0.2.tgz", @@ -1408,6 +2759,42 @@ "engines": { "node": ">=0.4" } + }, + "node_modules/zip-stream": { + "version": "6.0.1", + "resolved": "https://registry.npmjs.org/zip-stream/-/zip-stream-6.0.1.tgz", + "integrity": "sha512-zK7YHHz4ZXpW89AHXUPbQVGKI7uvkd3hzusTdotCg1UxyaVtg0zFJSTfW/Dq5f7OBBVnq6cZIaC8Ti4hb6dtCA==", + "dependencies": { + "archiver-utils": "^5.0.0", + "compress-commons": "^6.0.2", + "readable-stream": "^4.0.0" + }, + "engines": { + "node": ">= 14" + } + }, + "node_modules/zip-stream/node_modules/readable-stream": { + "version": "4.7.0", + "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-4.7.0.tgz", + "integrity": "sha512-oIGGmcpTLwPga8Bn6/Z75SVaH1z5dUut2ibSyAMVhmUggWpmDn2dapB0n7f8nwaSiRtepAsfJyfXIO5DCVAODg==", + "dependencies": { + "abort-controller": "^3.0.0", + "buffer": "^6.0.3", + "events": "^3.3.0", + "process": "^0.11.10", + "string_decoder": "^1.3.0" + }, + "engines": { + "node": "^12.22.0 || ^14.17.0 || >=16.0.0" + } + }, + "node_modules/zip-stream/node_modules/string_decoder": { + "version": "1.3.0", + "resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-1.3.0.tgz", + "integrity": "sha512-hkRX8U1WjJFd8LsDJ2yQ/wWWxaopEsABU1XfkM8A+j0+85JAGppt16cr1Whg6KIbb4okU6Mql6BOj+uup/wKeA==", + "dependencies": { + "safe-buffer": "~5.2.0" + } } } } diff --git a/backend/node_modules/.prisma/client/edge.js b/backend/node_modules/.prisma/client/edge.js index 200fe5e5..54283ca3 100644 --- a/backend/node_modules/.prisma/client/edge.js +++ b/backend/node_modules/.prisma/client/edge.js @@ -105,6 +105,7 @@ exports.Prisma.UserScalarFieldEnum = { firstName: 'firstName', lastName: 'lastName', isActive: 'isActive', + tokenInvalidatedAt: 'tokenInvalidatedAt', customerId: 'customerId', createdAt: 'createdAt', updatedAt: 'updatedAt' @@ -227,6 +228,13 @@ exports.Prisma.EmailProviderConfigScalarFieldEnum = { passwordEncrypted: 'passwordEncrypted', domain: 'domain', defaultForwardEmail: 'defaultForwardEmail', + imapServer: 'imapServer', + imapPort: 'imapPort', + smtpServer: 'smtpServer', + smtpPort: 'smtpPort', + imapEncryption: 'imapEncryption', + smtpEncryption: 'smtpEncryption', + allowSelfSignedCerts: 'allowSelfSignedCerts', isActive: 'isActive', isDefault: 'isDefault', createdAt: 'createdAt', @@ -243,6 +251,36 @@ exports.Prisma.StressfreiEmailScalarFieldEnum = { isProvisioned: 'isProvisioned', provisionedAt: 'provisionedAt', provisionError: 'provisionError', + hasMailbox: 'hasMailbox', + emailPasswordEncrypted: 'emailPasswordEncrypted', + createdAt: 'createdAt', + updatedAt: 'updatedAt' +}; + +exports.Prisma.CachedEmailScalarFieldEnum = { + id: 'id', + stressfreiEmailId: 'stressfreiEmailId', + folder: 'folder', + messageId: 'messageId', + uid: 'uid', + subject: 'subject', + fromAddress: 'fromAddress', + fromName: 'fromName', + toAddresses: 'toAddresses', + ccAddresses: 'ccAddresses', + receivedAt: 'receivedAt', + textBody: 'textBody', + htmlBody: 'htmlBody', + hasAttachments: 'hasAttachments', + attachmentNames: 'attachmentNames', + contractId: 'contractId', + assignedAt: 'assignedAt', + assignedBy: 'assignedBy', + isAutoAssigned: 'isAutoAssigned', + isRead: 'isRead', + isStarred: 'isStarred', + isDeleted: 'isDeleted', + deletedAt: 'deletedAt', createdAt: 'createdAt', updatedAt: 'updatedAt' }; @@ -510,6 +548,17 @@ exports.EmailProviderType = exports.$Enums.EmailProviderType = { DIRECTADMIN: 'DIRECTADMIN' }; +exports.MailEncryption = exports.$Enums.MailEncryption = { + SSL: 'SSL', + STARTTLS: 'STARTTLS', + NONE: 'NONE' +}; + +exports.EmailFolder = exports.$Enums.EmailFolder = { + INBOX: 'INBOX', + SENT: 'SENT' +}; + exports.MeterType = exports.$Enums.MeterType = { ELECTRICITY: 'ELECTRICITY', GAS: 'GAS' @@ -560,6 +609,7 @@ exports.Prisma.ModelName = { IdentityDocument: 'IdentityDocument', EmailProviderConfig: 'EmailProviderConfig', StressfreiEmail: 'StressfreiEmail', + CachedEmail: 'CachedEmail', Meter: 'Meter', MeterReading: 'MeterReading', SalesPlatform: 'SalesPlatform', @@ -617,7 +667,6 @@ const config = { "db" ], "activeProvider": "mysql", - "postinstall": false, "inlineDatasources": { "db": { "url": { @@ -626,13 +675,13 @@ const config = { } } }, - "inlineSchema": "generator client {\n provider = \"prisma-client-js\"\n}\n\ndatasource db {\n provider = \"mysql\"\n url = env(\"DATABASE_URL\")\n}\n\n// ==================== APP SETTINGS ====================\n\nmodel AppSetting {\n id Int @id @default(autoincrement())\n key String @unique\n value String @db.Text\n createdAt DateTime @default(now())\n updatedAt DateTime @updatedAt\n}\n\n// ==================== USERS & AUTH ====================\n\nmodel User {\n id Int @id @default(autoincrement())\n email String @unique\n password String\n firstName String\n lastName String\n isActive Boolean @default(true)\n customerId Int? @unique\n customer Customer? @relation(fields: [customerId], references: [id])\n roles UserRole[]\n createdAt DateTime @default(now())\n updatedAt DateTime @updatedAt\n}\n\nmodel Role {\n id Int @id @default(autoincrement())\n name String @unique\n description String?\n permissions RolePermission[]\n users UserRole[]\n createdAt DateTime @default(now())\n updatedAt DateTime @updatedAt\n}\n\nmodel Permission {\n id Int @id @default(autoincrement())\n resource String\n action String\n roles RolePermission[]\n\n @@unique([resource, action])\n}\n\nmodel RolePermission {\n roleId Int\n permissionId Int\n role Role @relation(fields: [roleId], references: [id], onDelete: Cascade)\n permission Permission @relation(fields: [permissionId], references: [id], onDelete: Cascade)\n\n @@id([roleId, permissionId])\n}\n\nmodel UserRole {\n userId Int\n roleId Int\n user User @relation(fields: [userId], references: [id], onDelete: Cascade)\n role Role @relation(fields: [roleId], references: [id], onDelete: Cascade)\n\n @@id([userId, roleId])\n}\n\n// ==================== CUSTOMERS ====================\n\nenum CustomerType {\n PRIVATE\n BUSINESS\n}\n\nmodel Customer {\n id Int @id @default(autoincrement())\n customerNumber String @unique\n type CustomerType @default(PRIVATE)\n salutation String?\n firstName String\n lastName String\n companyName String?\n foundingDate DateTime? // Gründungsdatum (für Firmen)\n birthDate DateTime?\n birthPlace String?\n email String?\n phone String?\n mobile String?\n taxNumber String?\n businessRegistrationPath String? // PDF-Pfad zur Gewerbeanmeldung\n commercialRegisterPath String? // PDF-Pfad zum Handelsregisterauszug\n commercialRegisterNumber String? // Handelsregisternummer (Text)\n privacyPolicyPath String? // PDF-Pfad zur Datenschutzerklärung (für alle Kunden)\n notes String? @db.Text\n\n // ===== Portal-Zugangsdaten =====\n portalEnabled Boolean @default(false) // Portal aktiviert?\n portalEmail String? @unique // Portal-Login E-Mail\n portalPasswordHash String? // Gehashtes Passwort (für Login)\n portalPasswordEncrypted String? // Verschlüsseltes Passwort (für Anzeige)\n portalLastLogin DateTime? // Letzte Anmeldung\n\n user User?\n addresses Address[]\n bankCards BankCard[]\n identityDocuments IdentityDocument[]\n meters Meter[]\n stressfreiEmails StressfreiEmail[]\n contracts Contract[]\n\n // Vertreter-Beziehungen (Kunde kann für andere Kunden handeln)\n representingFor CustomerRepresentative[] @relation(\"RepresentativeCustomer\")\n representedBy CustomerRepresentative[] @relation(\"RepresentedCustomer\")\n\n createdAt DateTime @default(now())\n updatedAt DateTime @updatedAt\n}\n\n// ==================== CUSTOMER REPRESENTATIVES ====================\n// Vertretungsbeziehung: Ein Kunde kann die Verträge eines anderen Kunden einsehen\n// z.B. Sohn (representativeId) kann Verträge der Mutter (customerId) sehen\n\nmodel CustomerRepresentative {\n id Int @id @default(autoincrement())\n customerId Int // Der Kunde, dessen Verträge eingesehen werden (z.B. Mutter)\n customer Customer @relation(\"RepresentedCustomer\", fields: [customerId], references: [id], onDelete: Cascade)\n representativeId Int // Der Kunde, der einsehen darf (z.B. Sohn)\n representative Customer @relation(\"RepresentativeCustomer\", fields: [representativeId], references: [id], onDelete: Cascade)\n notes String? // Notizen zur Vertretung\n isActive Boolean @default(true)\n createdAt DateTime @default(now())\n updatedAt DateTime @updatedAt\n\n @@unique([customerId, representativeId]) // Keine doppelten Einträge\n}\n\n// ==================== ADDRESSES ====================\n\nenum AddressType {\n DELIVERY_RESIDENCE\n BILLING\n}\n\nmodel Address {\n id Int @id @default(autoincrement())\n customerId Int\n customer Customer @relation(fields: [customerId], references: [id], onDelete: Cascade)\n type AddressType @default(DELIVERY_RESIDENCE)\n street String\n houseNumber String\n postalCode String\n city String\n country String @default(\"Deutschland\")\n isDefault Boolean @default(false)\n contracts Contract[]\n createdAt DateTime @default(now())\n updatedAt DateTime @updatedAt\n}\n\n// ==================== BANK CARDS ====================\n\nmodel BankCard {\n id Int @id @default(autoincrement())\n customerId Int\n customer Customer @relation(fields: [customerId], references: [id], onDelete: Cascade)\n accountHolder String\n iban String\n bic String?\n bankName String?\n expiryDate DateTime?\n documentPath String? // Pfad zur hochgeladenen PDF\n isActive Boolean @default(true)\n contracts Contract[]\n createdAt DateTime @default(now())\n updatedAt DateTime @updatedAt\n}\n\n// ==================== IDENTITY DOCUMENTS ====================\n\nenum DocumentType {\n ID_CARD\n PASSPORT\n DRIVERS_LICENSE\n OTHER\n}\n\nmodel IdentityDocument {\n id Int @id @default(autoincrement())\n customerId Int\n customer Customer @relation(fields: [customerId], references: [id], onDelete: Cascade)\n type DocumentType @default(ID_CARD)\n documentNumber String\n issuingAuthority String?\n issueDate DateTime?\n expiryDate DateTime?\n documentPath String? // Pfad zur hochgeladenen PDF\n isActive Boolean @default(true)\n // Führerschein-spezifische Felder\n licenseClasses String? // z.B. \"B, BE, AM, L\" - kommasepariert\n licenseIssueDate DateTime? // Datum des Führerscheinerwerbs (Klasse B)\n contracts Contract[]\n createdAt DateTime @default(now())\n updatedAt DateTime @updatedAt\n}\n\n// ==================== EMAIL PROVIDER CONFIG (Plesk, cPanel etc.) ====================\n\nenum EmailProviderType {\n PLESK\n CPANEL\n DIRECTADMIN\n}\n\nmodel EmailProviderConfig {\n id Int @id @default(autoincrement())\n name String @unique // z.B. \"Plesk Hauptserver\"\n type EmailProviderType\n apiUrl String // API-URL (z.B. https://server.de:8443)\n apiKey String? // API-Key (verschlüsselt)\n username String? // Benutzername für API\n passwordEncrypted String? // Passwort (verschlüsselt)\n domain String // Domain für E-Mails (z.B. stressfrei-wechseln.de)\n defaultForwardEmail String? // Standard-Weiterleitungsadresse (unsere eigene)\n isActive Boolean @default(true)\n isDefault Boolean @default(false) // Standard-Provider\n createdAt DateTime @default(now())\n updatedAt DateTime @updatedAt\n}\n\n// ==================== STRESSFREI-WECHSELN EMAIL ADDRESSES ====================\n\nmodel StressfreiEmail {\n id Int @id @default(autoincrement())\n customerId Int\n customer Customer @relation(fields: [customerId], references: [id], onDelete: Cascade)\n email String // Die Weiterleitungs-E-Mail-Adresse\n platform String? // Für welche Plattform (z.B. \"Freenet\", \"Klarmobil\")\n notes String? @db.Text // Optionale Notizen\n isActive Boolean @default(true)\n isProvisioned Boolean @default(false) // Wurde bei Provider angelegt?\n provisionedAt DateTime? // Wann wurde provisioniert?\n provisionError String? @db.Text // Fehlermeldung falls Provisionierung fehlschlug\n contracts Contract[] // Verträge die diese E-Mail als Benutzername verwenden\n createdAt DateTime @default(now())\n updatedAt DateTime @updatedAt\n}\n\n// ==================== METERS (Energy) ====================\n\nenum MeterType {\n ELECTRICITY\n GAS\n}\n\nmodel Meter {\n id Int @id @default(autoincrement())\n customerId Int\n customer Customer @relation(fields: [customerId], references: [id], onDelete: Cascade)\n meterNumber String\n type MeterType\n location String?\n isActive Boolean @default(true)\n readings MeterReading[]\n energyDetails EnergyContractDetails[]\n createdAt DateTime @default(now())\n updatedAt DateTime @updatedAt\n}\n\nmodel MeterReading {\n id Int @id @default(autoincrement())\n meterId Int\n meter Meter @relation(fields: [meterId], references: [id], onDelete: Cascade)\n readingDate DateTime\n value Float\n unit String @default(\"kWh\")\n notes String?\n createdAt DateTime @default(now())\n}\n\n// ==================== SALES PLATFORMS ====================\n\nmodel SalesPlatform {\n id Int @id @default(autoincrement())\n name String @unique\n contactInfo String? @db.Text\n isActive Boolean @default(true)\n contracts Contract[]\n createdAt DateTime @default(now())\n updatedAt DateTime @updatedAt\n}\n\n// ==================== CANCELLATION PERIODS ====================\n\nmodel CancellationPeriod {\n id Int @id @default(autoincrement())\n code String @unique // z.B. \"14T\", \"1M\", \"3M\", \"12M\", \"1J\"\n description String // z.B. \"14 Tage\", \"1 Monat\", \"3 Monate\"\n isActive Boolean @default(true)\n contracts Contract[]\n createdAt DateTime @default(now())\n updatedAt DateTime @updatedAt\n}\n\n// ==================== CONTRACT DURATIONS ====================\n\nmodel ContractDuration {\n id Int @id @default(autoincrement())\n code String @unique // z.B. \"12M\", \"24M\", \"1J\", \"2J\"\n description String // z.B. \"12 Monate\", \"24 Monate\", \"1 Jahr\"\n isActive Boolean @default(true)\n contracts Contract[]\n createdAt DateTime @default(now())\n updatedAt DateTime @updatedAt\n}\n\n// ==================== PROVIDERS (Anbieter) ====================\n\nmodel Provider {\n id Int @id @default(autoincrement())\n name String @unique // Anbietername\n portalUrl String? // Kundenkontourl (Login-Seite)\n usernameFieldName String? // Benutzernamefeld (z.B. \"email\", \"username\")\n passwordFieldName String? // Kennwortfeld (z.B. \"password\", \"pwd\")\n isActive Boolean @default(true)\n tariffs Tariff[]\n contracts Contract[]\n createdAt DateTime @default(now())\n updatedAt DateTime @updatedAt\n}\n\n// ==================== TARIFFS (Tarife) ====================\n\nmodel Tariff {\n id Int @id @default(autoincrement())\n providerId Int\n provider Provider @relation(fields: [providerId], references: [id], onDelete: Cascade)\n name String // Tarifname\n isActive Boolean @default(true)\n contracts Contract[]\n createdAt DateTime @default(now())\n updatedAt DateTime @updatedAt\n\n @@unique([providerId, name]) // Eindeutiger Tarif pro Anbieter\n}\n\n// ==================== CONTRACT CATEGORIES ====================\n\nmodel ContractCategory {\n id Int @id @default(autoincrement())\n code String @unique // Technischer Code (z.B. ELECTRICITY, GAS)\n name String // Anzeigename (z.B. Strom, Gas)\n icon String? // Icon-Name für UI (z.B. \"Zap\", \"Flame\")\n color String? // Farbe für UI (z.B. \"#FFC107\")\n sortOrder Int @default(0)\n isActive Boolean @default(true)\n contracts Contract[]\n createdAt DateTime @default(now())\n updatedAt DateTime @updatedAt\n}\n\n// ==================== CONTRACTS ====================\n\n// Legacy Enum - wird durch ContractCategory ersetzt\nenum ContractType {\n ELECTRICITY\n GAS\n DSL\n CABLE\n FIBER\n MOBILE\n TV\n CAR_INSURANCE\n}\n\nenum ContractStatus {\n DRAFT\n PENDING\n ACTIVE\n CANCELLED\n EXPIRED\n DEACTIVATED\n}\n\nmodel Contract {\n id Int @id @default(autoincrement())\n contractNumber String @unique\n customerId Int\n customer Customer @relation(fields: [customerId], references: [id], onDelete: Cascade)\n type ContractType\n status ContractStatus @default(DRAFT)\n\n // Neue konfigurierbare Kategorie (ersetzt langfristig das type-Enum)\n contractCategoryId Int?\n contractCategory ContractCategory? @relation(fields: [contractCategoryId], references: [id])\n\n addressId Int?\n address Address? @relation(fields: [addressId], references: [id])\n\n bankCardId Int?\n bankCard BankCard? @relation(fields: [bankCardId], references: [id])\n\n identityDocumentId Int?\n identityDocument IdentityDocument? @relation(fields: [identityDocumentId], references: [id])\n\n salesPlatformId Int?\n salesPlatform SalesPlatform? @relation(fields: [salesPlatformId], references: [id])\n\n cancellationPeriodId Int?\n cancellationPeriod CancellationPeriod? @relation(fields: [cancellationPeriodId], references: [id])\n\n contractDurationId Int?\n contractDuration ContractDuration? @relation(fields: [contractDurationId], references: [id])\n\n previousContractId Int? @unique\n previousContract Contract? @relation(\"ContractHistory\", fields: [previousContractId], references: [id])\n followUpContract Contract? @relation(\"ContractHistory\")\n\n // Anbieter & Tarif (neue Verknüpfung)\n providerId Int?\n provider Provider? @relation(fields: [providerId], references: [id])\n tariffId Int?\n tariff Tariff? @relation(fields: [tariffId], references: [id])\n\n // Legacy-Felder (für Abwärtskompatibilität)\n providerName String?\n tariffName String?\n customerNumberAtProvider String?\n priceFirst12Months String? // Preis erste 12 Monate\n priceFrom13Months String? // Preis ab 13. Monat\n priceAfter24Months String? // Preis nach 24 Monaten\n\n startDate DateTime?\n endDate DateTime? // Wird aus startDate + contractDuration berechnet\n commission Float?\n\n // Kündigungsdokumente\n cancellationLetterPath String? // Kündigungsschreiben PDF\n cancellationConfirmationPath String? // Kündigungsbestätigung PDF\n cancellationLetterOptionsPath String? // Kündigungsschreiben Optionen PDF\n cancellationConfirmationOptionsPath String? // Kündigungsbestätigung Optionen PDF\n\n // Kündigungsdaten\n cancellationConfirmationDate DateTime? // Kündigungsbestätigungsdatum\n cancellationConfirmationOptionsDate DateTime? // Kündigungsbestätigungsoptionendatum\n wasSpecialCancellation Boolean @default(false) // Wurde sondergekündigt?\n\n portalUsername String?\n portalPasswordEncrypted String?\n\n // Stressfrei-Wechseln E-Mail als Benutzername (Alternative zu portalUsername)\n stressfreiEmailId Int?\n stressfreiEmail StressfreiEmail? @relation(fields: [stressfreiEmailId], references: [id])\n\n notes String? @db.Text\n\n energyDetails EnergyContractDetails?\n internetDetails InternetContractDetails?\n mobileDetails MobileContractDetails?\n tvDetails TvContractDetails?\n carInsuranceDetails CarInsuranceDetails?\n\n tasks ContractTask[]\n\n createdAt DateTime @default(now())\n updatedAt DateTime @updatedAt\n}\n\n// ==================== CONTRACT TASKS ====================\n\nenum ContractTaskStatus {\n OPEN\n COMPLETED\n}\n\nmodel ContractTask {\n id Int @id @default(autoincrement())\n contractId Int\n contract Contract @relation(fields: [contractId], references: [id], onDelete: Cascade)\n title String\n description String? @db.Text\n status ContractTaskStatus @default(OPEN)\n visibleInPortal Boolean @default(false)\n createdBy String? // Name des Erstellers\n completedAt DateTime?\n subtasks ContractTaskSubtask[]\n createdAt DateTime @default(now())\n updatedAt DateTime @updatedAt\n}\n\nmodel ContractTaskSubtask {\n id Int @id @default(autoincrement())\n taskId Int\n task ContractTask @relation(fields: [taskId], references: [id], onDelete: Cascade)\n title String\n status ContractTaskStatus @default(OPEN)\n createdBy String?\n completedAt DateTime?\n createdAt DateTime @default(now())\n updatedAt DateTime @updatedAt\n}\n\n// ==================== ENERGY CONTRACT DETAILS ====================\n\nmodel EnergyContractDetails {\n id Int @id @default(autoincrement())\n contractId Int @unique\n contract Contract @relation(fields: [contractId], references: [id], onDelete: Cascade)\n meterId Int?\n meter Meter? @relation(fields: [meterId], references: [id])\n annualConsumption Float?\n basePrice Float?\n unitPrice Float?\n bonus Float?\n previousProviderName String?\n previousCustomerNumber String?\n}\n\n// ==================== INTERNET CONTRACT DETAILS ====================\n\nmodel InternetContractDetails {\n id Int @id @default(autoincrement())\n contractId Int @unique\n contract Contract @relation(fields: [contractId], references: [id], onDelete: Cascade)\n downloadSpeed Int?\n uploadSpeed Int?\n routerModel String?\n routerSerialNumber String?\n installationDate DateTime?\n // Internet-Zugangsdaten\n internetUsername String?\n internetPasswordEncrypted String? // Verschlüsselt gespeichert\n // Glasfaser-spezifisch\n homeId String?\n // Vodafone DSL/Kabel spezifisch\n activationCode String?\n phoneNumbers PhoneNumber[]\n}\n\nmodel PhoneNumber {\n id Int @id @default(autoincrement())\n internetContractDetailsId Int\n internetDetails InternetContractDetails @relation(fields: [internetContractDetailsId], references: [id], onDelete: Cascade)\n phoneNumber String\n isMain Boolean @default(false)\n // SIP-Zugangsdaten\n sipUsername String?\n sipPasswordEncrypted String? // Verschlüsselt gespeichert\n sipServer String?\n}\n\n// ==================== MOBILE CONTRACT DETAILS ====================\n\nmodel MobileContractDetails {\n id Int @id @default(autoincrement())\n contractId Int @unique\n contract Contract @relation(fields: [contractId], references: [id], onDelete: Cascade)\n requiresMultisim Boolean @default(false) // Multisim erforderlich?\n dataVolume Float?\n includedMinutes Int?\n includedSMS Int?\n deviceModel String?\n deviceImei String?\n simCards SimCard[]\n // Legacy-Felder (für Abwärtskompatibilität, werden durch simCards ersetzt)\n phoneNumber String?\n simCardNumber String?\n}\n\nmodel SimCard {\n id Int @id @default(autoincrement())\n mobileDetailsId Int\n mobileDetails MobileContractDetails @relation(fields: [mobileDetailsId], references: [id], onDelete: Cascade)\n phoneNumber String? // Rufnummer\n simCardNumber String? // SIM-Kartennummer\n pin String? // PIN (verschlüsselt gespeichert)\n puk String? // PUK (verschlüsselt gespeichert)\n isMultisim Boolean @default(false) // Ist dies eine Multisim-Karte?\n isMain Boolean @default(false) // Ist dies die Hauptkarte?\n createdAt DateTime @default(now())\n updatedAt DateTime @updatedAt\n}\n\n// ==================== TV CONTRACT DETAILS ====================\n\nmodel TvContractDetails {\n id Int @id @default(autoincrement())\n contractId Int @unique\n contract Contract @relation(fields: [contractId], references: [id], onDelete: Cascade)\n receiverModel String?\n smartcardNumber String?\n package String?\n}\n\n// ==================== CAR INSURANCE DETAILS ====================\n\nenum InsuranceType {\n LIABILITY\n PARTIAL\n FULL\n}\n\nmodel CarInsuranceDetails {\n id Int @id @default(autoincrement())\n contractId Int @unique\n contract Contract @relation(fields: [contractId], references: [id], onDelete: Cascade)\n licensePlate String?\n hsn String?\n tsn String?\n vin String?\n vehicleType String?\n firstRegistration DateTime?\n noClaimsClass String?\n insuranceType InsuranceType @default(LIABILITY)\n deductiblePartial Float?\n deductibleFull Float?\n policyNumber String?\n previousInsurer String?\n}\n", - "inlineSchemaHash": "36ecbca17fa945f160ba1bb4a7cfa1b4971e63c59c4e05b0dcc483003048b598", + "inlineSchema": "generator client {\n provider = \"prisma-client-js\"\n}\n\ndatasource db {\n provider = \"mysql\"\n url = env(\"DATABASE_URL\")\n}\n\n// ==================== APP SETTINGS ====================\n\nmodel AppSetting {\n id Int @id @default(autoincrement())\n key String @unique\n value String @db.Text\n createdAt DateTime @default(now())\n updatedAt DateTime @updatedAt\n}\n\n// ==================== USERS & AUTH ====================\n\nmodel User {\n id Int @id @default(autoincrement())\n email String @unique\n password String\n firstName String\n lastName String\n isActive Boolean @default(true)\n tokenInvalidatedAt DateTime? // Zeitpunkt ab dem alle Tokens ungültig sind (für Zwangslogout bei Rechteänderung)\n customerId Int? @unique\n customer Customer? @relation(fields: [customerId], references: [id])\n roles UserRole[]\n createdAt DateTime @default(now())\n updatedAt DateTime @updatedAt\n}\n\nmodel Role {\n id Int @id @default(autoincrement())\n name String @unique\n description String?\n permissions RolePermission[]\n users UserRole[]\n createdAt DateTime @default(now())\n updatedAt DateTime @updatedAt\n}\n\nmodel Permission {\n id Int @id @default(autoincrement())\n resource String\n action String\n roles RolePermission[]\n\n @@unique([resource, action])\n}\n\nmodel RolePermission {\n roleId Int\n permissionId Int\n role Role @relation(fields: [roleId], references: [id], onDelete: Cascade)\n permission Permission @relation(fields: [permissionId], references: [id], onDelete: Cascade)\n\n @@id([roleId, permissionId])\n}\n\nmodel UserRole {\n userId Int\n roleId Int\n user User @relation(fields: [userId], references: [id], onDelete: Cascade)\n role Role @relation(fields: [roleId], references: [id], onDelete: Cascade)\n\n @@id([userId, roleId])\n}\n\n// ==================== CUSTOMERS ====================\n\nenum CustomerType {\n PRIVATE\n BUSINESS\n}\n\nmodel Customer {\n id Int @id @default(autoincrement())\n customerNumber String @unique\n type CustomerType @default(PRIVATE)\n salutation String?\n firstName String\n lastName String\n companyName String?\n foundingDate DateTime? // Gründungsdatum (für Firmen)\n birthDate DateTime?\n birthPlace String?\n email String?\n phone String?\n mobile String?\n taxNumber String?\n businessRegistrationPath String? // PDF-Pfad zur Gewerbeanmeldung\n commercialRegisterPath String? // PDF-Pfad zum Handelsregisterauszug\n commercialRegisterNumber String? // Handelsregisternummer (Text)\n privacyPolicyPath String? // PDF-Pfad zur Datenschutzerklärung (für alle Kunden)\n notes String? @db.Text\n\n // ===== Portal-Zugangsdaten =====\n portalEnabled Boolean @default(false) // Portal aktiviert?\n portalEmail String? @unique // Portal-Login E-Mail\n portalPasswordHash String? // Gehashtes Passwort (für Login)\n portalPasswordEncrypted String? // Verschlüsseltes Passwort (für Anzeige)\n portalLastLogin DateTime? // Letzte Anmeldung\n\n user User?\n addresses Address[]\n bankCards BankCard[]\n identityDocuments IdentityDocument[]\n meters Meter[]\n stressfreiEmails StressfreiEmail[]\n contracts Contract[]\n\n // Vertreter-Beziehungen (Kunde kann für andere Kunden handeln)\n representingFor CustomerRepresentative[] @relation(\"RepresentativeCustomer\")\n representedBy CustomerRepresentative[] @relation(\"RepresentedCustomer\")\n\n createdAt DateTime @default(now())\n updatedAt DateTime @updatedAt\n}\n\n// ==================== CUSTOMER REPRESENTATIVES ====================\n// Vertretungsbeziehung: Ein Kunde kann die Verträge eines anderen Kunden einsehen\n// z.B. Sohn (representativeId) kann Verträge der Mutter (customerId) sehen\n\nmodel CustomerRepresentative {\n id Int @id @default(autoincrement())\n customerId Int // Der Kunde, dessen Verträge eingesehen werden (z.B. Mutter)\n customer Customer @relation(\"RepresentedCustomer\", fields: [customerId], references: [id], onDelete: Cascade)\n representativeId Int // Der Kunde, der einsehen darf (z.B. Sohn)\n representative Customer @relation(\"RepresentativeCustomer\", fields: [representativeId], references: [id], onDelete: Cascade)\n notes String? // Notizen zur Vertretung\n isActive Boolean @default(true)\n createdAt DateTime @default(now())\n updatedAt DateTime @updatedAt\n\n @@unique([customerId, representativeId]) // Keine doppelten Einträge\n}\n\n// ==================== ADDRESSES ====================\n\nenum AddressType {\n DELIVERY_RESIDENCE\n BILLING\n}\n\nmodel Address {\n id Int @id @default(autoincrement())\n customerId Int\n customer Customer @relation(fields: [customerId], references: [id], onDelete: Cascade)\n type AddressType @default(DELIVERY_RESIDENCE)\n street String\n houseNumber String\n postalCode String\n city String\n country String @default(\"Deutschland\")\n isDefault Boolean @default(false)\n contracts Contract[]\n createdAt DateTime @default(now())\n updatedAt DateTime @updatedAt\n}\n\n// ==================== BANK CARDS ====================\n\nmodel BankCard {\n id Int @id @default(autoincrement())\n customerId Int\n customer Customer @relation(fields: [customerId], references: [id], onDelete: Cascade)\n accountHolder String\n iban String\n bic String?\n bankName String?\n expiryDate DateTime?\n documentPath String? // Pfad zur hochgeladenen PDF\n isActive Boolean @default(true)\n contracts Contract[]\n createdAt DateTime @default(now())\n updatedAt DateTime @updatedAt\n}\n\n// ==================== IDENTITY DOCUMENTS ====================\n\nenum DocumentType {\n ID_CARD\n PASSPORT\n DRIVERS_LICENSE\n OTHER\n}\n\nmodel IdentityDocument {\n id Int @id @default(autoincrement())\n customerId Int\n customer Customer @relation(fields: [customerId], references: [id], onDelete: Cascade)\n type DocumentType @default(ID_CARD)\n documentNumber String\n issuingAuthority String?\n issueDate DateTime?\n expiryDate DateTime?\n documentPath String? // Pfad zur hochgeladenen PDF\n isActive Boolean @default(true)\n // Führerschein-spezifische Felder\n licenseClasses String? // z.B. \"B, BE, AM, L\" - kommasepariert\n licenseIssueDate DateTime? // Datum des Führerscheinerwerbs (Klasse B)\n contracts Contract[]\n createdAt DateTime @default(now())\n updatedAt DateTime @updatedAt\n}\n\n// ==================== EMAIL PROVIDER CONFIG (Plesk, cPanel etc.) ====================\n\nenum EmailProviderType {\n PLESK\n CPANEL\n DIRECTADMIN\n}\n\n// Verschlüsselungstyp für E-Mail-Verbindungen\nenum MailEncryption {\n SSL // Implicit SSL/TLS (Ports 465/993) - Verschlüsselung von Anfang an\n STARTTLS // STARTTLS (Ports 587/143) - Startet unverschlüsselt, dann Upgrade\n NONE // Keine Verschlüsselung (Ports 25/143)\n}\n\nmodel EmailProviderConfig {\n id Int @id @default(autoincrement())\n name String @unique // z.B. \"Plesk Hauptserver\"\n type EmailProviderType\n apiUrl String // API-URL (z.B. https://server.de:8443)\n apiKey String? // API-Key (verschlüsselt)\n username String? // Benutzername für API\n passwordEncrypted String? // Passwort (verschlüsselt)\n domain String // Domain für E-Mails (z.B. stressfrei-wechseln.de)\n defaultForwardEmail String? // Standard-Weiterleitungsadresse (unsere eigene)\n\n // IMAP/SMTP-Server für E-Mail-Client (optional, default: mail.{domain})\n imapServer String? // z.B. \"mail.stressfrei-wechseln.de\"\n imapPort Int? @default(993)\n smtpServer String?\n smtpPort Int? @default(465)\n\n // Verschlüsselungs-Einstellungen\n imapEncryption MailEncryption @default(SSL) // SSL, STARTTLS oder NONE\n smtpEncryption MailEncryption @default(SSL) // SSL, STARTTLS oder NONE\n allowSelfSignedCerts Boolean @default(false) // Selbstsignierte Zertifikate erlauben\n\n isActive Boolean @default(true)\n isDefault Boolean @default(false) // Standard-Provider\n createdAt DateTime @default(now())\n updatedAt DateTime @updatedAt\n}\n\n// ==================== STRESSFREI-WECHSELN EMAIL ADDRESSES ====================\n\nmodel StressfreiEmail {\n id Int @id @default(autoincrement())\n customerId Int\n customer Customer @relation(fields: [customerId], references: [id], onDelete: Cascade)\n email String // Die Weiterleitungs-E-Mail-Adresse\n platform String? // Für welche Plattform (z.B. \"Freenet\", \"Klarmobil\")\n notes String? @db.Text // Optionale Notizen\n isActive Boolean @default(true)\n isProvisioned Boolean @default(false) // Wurde bei Provider angelegt?\n provisionedAt DateTime? // Wann wurde provisioniert?\n provisionError String? @db.Text // Fehlermeldung falls Provisionierung fehlschlug\n\n // Mailbox-Zugangsdaten (für IMAP/SMTP-Zugang)\n hasMailbox Boolean @default(false) // Hat echte Mailbox (nicht nur Weiterleitung)?\n emailPasswordEncrypted String? // Verschlüsseltes Mailbox-Passwort (AES-256-GCM)\n\n contracts Contract[] // Verträge die diese E-Mail als Benutzername verwenden\n cachedEmails CachedEmail[] // Gecachte E-Mails aus dieser Mailbox\n createdAt DateTime @default(now())\n updatedAt DateTime @updatedAt\n}\n\n// ==================== CACHED EMAILS (E-Mail-Client) ====================\n\nenum EmailFolder {\n INBOX\n SENT\n}\n\nmodel CachedEmail {\n id Int @id @default(autoincrement())\n stressfreiEmailId Int\n stressfreiEmail StressfreiEmail @relation(fields: [stressfreiEmailId], references: [id], onDelete: Cascade)\n\n // Ordner (Posteingang oder Gesendet)\n folder EmailFolder @default(INBOX)\n\n // IMAP-Identifikation\n messageId String // RFC 5322 Message-ID\n uid Int // IMAP UID (für Synchronisierung, bei SENT = 0)\n\n // E-Mail-Metadaten\n subject String?\n fromAddress String\n fromName String?\n toAddresses String @db.Text // JSON Array\n ccAddresses String? @db.Text // JSON Array\n receivedAt DateTime\n\n // Inhalt\n textBody String? @db.LongText\n htmlBody String? @db.LongText\n hasAttachments Boolean @default(false)\n attachmentNames String? @db.Text // JSON Array\n\n // Vertragszuordnung\n contractId Int?\n contract Contract? @relation(fields: [contractId], references: [id], onDelete: SetNull)\n assignedAt DateTime?\n assignedBy Int? // User ID der die Zuordnung gemacht hat\n isAutoAssigned Boolean @default(false) // true = automatisch beim Senden aus Vertrag\n\n // Flags\n isRead Boolean @default(false)\n isStarred Boolean @default(false)\n\n // Papierkorb\n isDeleted Boolean @default(false) // Im Papierkorb?\n deletedAt DateTime? // Wann gelöscht?\n\n createdAt DateTime @default(now())\n updatedAt DateTime @updatedAt\n\n @@unique([stressfreiEmailId, messageId, folder]) // Folder hinzugefügt: gleiche MessageID kann in INBOX und SENT existieren\n @@index([contractId])\n @@index([stressfreiEmailId, folder, receivedAt])\n @@index([stressfreiEmailId, isDeleted]) // Für Papierkorb-Abfragen\n}\n\n// ==================== METERS (Energy) ====================\n\nenum MeterType {\n ELECTRICITY\n GAS\n}\n\nmodel Meter {\n id Int @id @default(autoincrement())\n customerId Int\n customer Customer @relation(fields: [customerId], references: [id], onDelete: Cascade)\n meterNumber String\n type MeterType\n location String?\n isActive Boolean @default(true)\n readings MeterReading[]\n energyDetails EnergyContractDetails[]\n createdAt DateTime @default(now())\n updatedAt DateTime @updatedAt\n}\n\nmodel MeterReading {\n id Int @id @default(autoincrement())\n meterId Int\n meter Meter @relation(fields: [meterId], references: [id], onDelete: Cascade)\n readingDate DateTime\n value Float\n unit String @default(\"kWh\")\n notes String?\n createdAt DateTime @default(now())\n}\n\n// ==================== SALES PLATFORMS ====================\n\nmodel SalesPlatform {\n id Int @id @default(autoincrement())\n name String @unique\n contactInfo String? @db.Text\n isActive Boolean @default(true)\n contracts Contract[]\n createdAt DateTime @default(now())\n updatedAt DateTime @updatedAt\n}\n\n// ==================== CANCELLATION PERIODS ====================\n\nmodel CancellationPeriod {\n id Int @id @default(autoincrement())\n code String @unique // z.B. \"14T\", \"1M\", \"3M\", \"12M\", \"1J\"\n description String // z.B. \"14 Tage\", \"1 Monat\", \"3 Monate\"\n isActive Boolean @default(true)\n contracts Contract[]\n createdAt DateTime @default(now())\n updatedAt DateTime @updatedAt\n}\n\n// ==================== CONTRACT DURATIONS ====================\n\nmodel ContractDuration {\n id Int @id @default(autoincrement())\n code String @unique // z.B. \"12M\", \"24M\", \"1J\", \"2J\"\n description String // z.B. \"12 Monate\", \"24 Monate\", \"1 Jahr\"\n isActive Boolean @default(true)\n contracts Contract[]\n createdAt DateTime @default(now())\n updatedAt DateTime @updatedAt\n}\n\n// ==================== PROVIDERS (Anbieter) ====================\n\nmodel Provider {\n id Int @id @default(autoincrement())\n name String @unique // Anbietername\n portalUrl String? // Kundenkontourl (Login-Seite)\n usernameFieldName String? // Benutzernamefeld (z.B. \"email\", \"username\")\n passwordFieldName String? // Kennwortfeld (z.B. \"password\", \"pwd\")\n isActive Boolean @default(true)\n tariffs Tariff[]\n contracts Contract[]\n createdAt DateTime @default(now())\n updatedAt DateTime @updatedAt\n}\n\n// ==================== TARIFFS (Tarife) ====================\n\nmodel Tariff {\n id Int @id @default(autoincrement())\n providerId Int\n provider Provider @relation(fields: [providerId], references: [id], onDelete: Cascade)\n name String // Tarifname\n isActive Boolean @default(true)\n contracts Contract[]\n createdAt DateTime @default(now())\n updatedAt DateTime @updatedAt\n\n @@unique([providerId, name]) // Eindeutiger Tarif pro Anbieter\n}\n\n// ==================== CONTRACT CATEGORIES ====================\n\nmodel ContractCategory {\n id Int @id @default(autoincrement())\n code String @unique // Technischer Code (z.B. ELECTRICITY, GAS)\n name String // Anzeigename (z.B. Strom, Gas)\n icon String? // Icon-Name für UI (z.B. \"Zap\", \"Flame\")\n color String? // Farbe für UI (z.B. \"#FFC107\")\n sortOrder Int @default(0)\n isActive Boolean @default(true)\n contracts Contract[]\n createdAt DateTime @default(now())\n updatedAt DateTime @updatedAt\n}\n\n// ==================== CONTRACTS ====================\n\n// Legacy Enum - wird durch ContractCategory ersetzt\nenum ContractType {\n ELECTRICITY\n GAS\n DSL\n CABLE\n FIBER\n MOBILE\n TV\n CAR_INSURANCE\n}\n\nenum ContractStatus {\n DRAFT\n PENDING\n ACTIVE\n CANCELLED\n EXPIRED\n DEACTIVATED\n}\n\nmodel Contract {\n id Int @id @default(autoincrement())\n contractNumber String @unique\n customerId Int\n customer Customer @relation(fields: [customerId], references: [id], onDelete: Cascade)\n type ContractType\n status ContractStatus @default(DRAFT)\n\n // Neue konfigurierbare Kategorie (ersetzt langfristig das type-Enum)\n contractCategoryId Int?\n contractCategory ContractCategory? @relation(fields: [contractCategoryId], references: [id])\n\n addressId Int?\n address Address? @relation(fields: [addressId], references: [id])\n\n bankCardId Int?\n bankCard BankCard? @relation(fields: [bankCardId], references: [id])\n\n identityDocumentId Int?\n identityDocument IdentityDocument? @relation(fields: [identityDocumentId], references: [id])\n\n salesPlatformId Int?\n salesPlatform SalesPlatform? @relation(fields: [salesPlatformId], references: [id])\n\n cancellationPeriodId Int?\n cancellationPeriod CancellationPeriod? @relation(fields: [cancellationPeriodId], references: [id])\n\n contractDurationId Int?\n contractDuration ContractDuration? @relation(fields: [contractDurationId], references: [id])\n\n previousContractId Int? @unique\n previousContract Contract? @relation(\"ContractHistory\", fields: [previousContractId], references: [id])\n followUpContract Contract? @relation(\"ContractHistory\")\n\n // Anbieter & Tarif (neue Verknüpfung)\n providerId Int?\n provider Provider? @relation(fields: [providerId], references: [id])\n tariffId Int?\n tariff Tariff? @relation(fields: [tariffId], references: [id])\n\n // Legacy-Felder (für Abwärtskompatibilität)\n providerName String?\n tariffName String?\n customerNumberAtProvider String?\n priceFirst12Months String? // Preis erste 12 Monate\n priceFrom13Months String? // Preis ab 13. Monat\n priceAfter24Months String? // Preis nach 24 Monaten\n\n startDate DateTime?\n endDate DateTime? // Wird aus startDate + contractDuration berechnet\n commission Float?\n\n // Kündigungsdokumente\n cancellationLetterPath String? // Kündigungsschreiben PDF\n cancellationConfirmationPath String? // Kündigungsbestätigung PDF\n cancellationLetterOptionsPath String? // Kündigungsschreiben Optionen PDF\n cancellationConfirmationOptionsPath String? // Kündigungsbestätigung Optionen PDF\n\n // Kündigungsdaten\n cancellationConfirmationDate DateTime? // Kündigungsbestätigungsdatum\n cancellationConfirmationOptionsDate DateTime? // Kündigungsbestätigungsoptionendatum\n wasSpecialCancellation Boolean @default(false) // Wurde sondergekündigt?\n\n portalUsername String?\n portalPasswordEncrypted String?\n\n // Stressfrei-Wechseln E-Mail als Benutzername (Alternative zu portalUsername)\n stressfreiEmailId Int?\n stressfreiEmail StressfreiEmail? @relation(fields: [stressfreiEmailId], references: [id])\n\n notes String? @db.Text\n\n energyDetails EnergyContractDetails?\n internetDetails InternetContractDetails?\n mobileDetails MobileContractDetails?\n tvDetails TvContractDetails?\n carInsuranceDetails CarInsuranceDetails?\n\n tasks ContractTask[]\n assignedEmails CachedEmail[] // Zugeordnete E-Mails aus dem E-Mail-Client\n\n createdAt DateTime @default(now())\n updatedAt DateTime @updatedAt\n}\n\n// ==================== CONTRACT TASKS ====================\n\nenum ContractTaskStatus {\n OPEN\n COMPLETED\n}\n\nmodel ContractTask {\n id Int @id @default(autoincrement())\n contractId Int\n contract Contract @relation(fields: [contractId], references: [id], onDelete: Cascade)\n title String\n description String? @db.Text\n status ContractTaskStatus @default(OPEN)\n visibleInPortal Boolean @default(false)\n createdBy String? // Name des Erstellers\n completedAt DateTime?\n subtasks ContractTaskSubtask[]\n createdAt DateTime @default(now())\n updatedAt DateTime @updatedAt\n}\n\nmodel ContractTaskSubtask {\n id Int @id @default(autoincrement())\n taskId Int\n task ContractTask @relation(fields: [taskId], references: [id], onDelete: Cascade)\n title String\n status ContractTaskStatus @default(OPEN)\n createdBy String?\n completedAt DateTime?\n createdAt DateTime @default(now())\n updatedAt DateTime @updatedAt\n}\n\n// ==================== ENERGY CONTRACT DETAILS ====================\n\nmodel EnergyContractDetails {\n id Int @id @default(autoincrement())\n contractId Int @unique\n contract Contract @relation(fields: [contractId], references: [id], onDelete: Cascade)\n meterId Int?\n meter Meter? @relation(fields: [meterId], references: [id])\n annualConsumption Float?\n basePrice Float?\n unitPrice Float?\n bonus Float?\n previousProviderName String?\n previousCustomerNumber String?\n}\n\n// ==================== INTERNET CONTRACT DETAILS ====================\n\nmodel InternetContractDetails {\n id Int @id @default(autoincrement())\n contractId Int @unique\n contract Contract @relation(fields: [contractId], references: [id], onDelete: Cascade)\n downloadSpeed Int?\n uploadSpeed Int?\n routerModel String?\n routerSerialNumber String?\n installationDate DateTime?\n // Internet-Zugangsdaten\n internetUsername String?\n internetPasswordEncrypted String? // Verschlüsselt gespeichert\n // Glasfaser-spezifisch\n homeId String?\n // Vodafone DSL/Kabel spezifisch\n activationCode String?\n phoneNumbers PhoneNumber[]\n}\n\nmodel PhoneNumber {\n id Int @id @default(autoincrement())\n internetContractDetailsId Int\n internetDetails InternetContractDetails @relation(fields: [internetContractDetailsId], references: [id], onDelete: Cascade)\n phoneNumber String\n isMain Boolean @default(false)\n // SIP-Zugangsdaten\n sipUsername String?\n sipPasswordEncrypted String? // Verschlüsselt gespeichert\n sipServer String?\n}\n\n// ==================== MOBILE CONTRACT DETAILS ====================\n\nmodel MobileContractDetails {\n id Int @id @default(autoincrement())\n contractId Int @unique\n contract Contract @relation(fields: [contractId], references: [id], onDelete: Cascade)\n requiresMultisim Boolean @default(false) // Multisim erforderlich?\n dataVolume Float?\n includedMinutes Int?\n includedSMS Int?\n deviceModel String?\n deviceImei String?\n simCards SimCard[]\n // Legacy-Felder (für Abwärtskompatibilität, werden durch simCards ersetzt)\n phoneNumber String?\n simCardNumber String?\n}\n\nmodel SimCard {\n id Int @id @default(autoincrement())\n mobileDetailsId Int\n mobileDetails MobileContractDetails @relation(fields: [mobileDetailsId], references: [id], onDelete: Cascade)\n phoneNumber String? // Rufnummer\n simCardNumber String? // SIM-Kartennummer\n pin String? // PIN (verschlüsselt gespeichert)\n puk String? // PUK (verschlüsselt gespeichert)\n isMultisim Boolean @default(false) // Ist dies eine Multisim-Karte?\n isMain Boolean @default(false) // Ist dies die Hauptkarte?\n createdAt DateTime @default(now())\n updatedAt DateTime @updatedAt\n}\n\n// ==================== TV CONTRACT DETAILS ====================\n\nmodel TvContractDetails {\n id Int @id @default(autoincrement())\n contractId Int @unique\n contract Contract @relation(fields: [contractId], references: [id], onDelete: Cascade)\n receiverModel String?\n smartcardNumber String?\n package String?\n}\n\n// ==================== CAR INSURANCE DETAILS ====================\n\nenum InsuranceType {\n LIABILITY\n PARTIAL\n FULL\n}\n\nmodel CarInsuranceDetails {\n id Int @id @default(autoincrement())\n contractId Int @unique\n contract Contract @relation(fields: [contractId], references: [id], onDelete: Cascade)\n licensePlate String?\n hsn String?\n tsn String?\n vin String?\n vehicleType String?\n firstRegistration DateTime?\n noClaimsClass String?\n insuranceType InsuranceType @default(LIABILITY)\n deductiblePartial Float?\n deductibleFull Float?\n policyNumber String?\n previousInsurer String?\n}\n", + "inlineSchemaHash": "0275307bf5bad35d995156e9cf00dc7906b05135b28bd545b6e7e6322aaa01ab", "copyEngine": true } config.dirname = '/' -config.runtimeDataModel = JSON.parse("{\"models\":{\"AppSetting\":{\"dbName\":null,\"fields\":[{\"name\":\"id\",\"kind\":\"scalar\",\"isList\":false,\"isRequired\":true,\"isUnique\":false,\"isId\":true,\"isReadOnly\":false,\"hasDefaultValue\":true,\"type\":\"Int\",\"default\":{\"name\":\"autoincrement\",\"args\":[]},\"isGenerated\":false,\"isUpdatedAt\":false},{\"name\":\"key\",\"kind\":\"scalar\",\"isList\":false,\"isRequired\":true,\"isUnique\":true,\"isId\":false,\"isReadOnly\":false,\"hasDefaultValue\":false,\"type\":\"String\",\"isGenerated\":false,\"isUpdatedAt\":false},{\"name\":\"value\",\"kind\":\"scalar\",\"isList\":false,\"isRequired\":true,\"isUnique\":false,\"isId\":false,\"isReadOnly\":false,\"hasDefaultValue\":false,\"type\":\"String\",\"isGenerated\":false,\"isUpdatedAt\":false},{\"name\":\"createdAt\",\"kind\":\"scalar\",\"isList\":false,\"isRequired\":true,\"isUnique\":false,\"isId\":false,\"isReadOnly\":false,\"hasDefaultValue\":true,\"type\":\"DateTime\",\"default\":{\"name\":\"now\",\"args\":[]},\"isGenerated\":false,\"isUpdatedAt\":false},{\"name\":\"updatedAt\",\"kind\":\"scalar\",\"isList\":false,\"isRequired\":true,\"isUnique\":false,\"isId\":false,\"isReadOnly\":false,\"hasDefaultValue\":false,\"type\":\"DateTime\",\"isGenerated\":false,\"isUpdatedAt\":true}],\"primaryKey\":null,\"uniqueFields\":[],\"uniqueIndexes\":[],\"isGenerated\":false},\"User\":{\"dbName\":null,\"fields\":[{\"name\":\"id\",\"kind\":\"scalar\",\"isList\":false,\"isRequired\":true,\"isUnique\":false,\"isId\":true,\"isReadOnly\":false,\"hasDefaultValue\":true,\"type\":\"Int\",\"default\":{\"name\":\"autoincrement\",\"args\":[]},\"isGenerated\":false,\"isUpdatedAt\":false},{\"name\":\"email\",\"kind\":\"scalar\",\"isList\":false,\"isRequired\":true,\"isUnique\":true,\"isId\":false,\"isReadOnly\":false,\"hasDefaultValue\":false,\"type\":\"String\",\"isGenerated\":false,\"isUpdatedAt\":false},{\"name\":\"password\",\"kind\":\"scalar\",\"isList\":false,\"isRequired\":true,\"isUnique\":false,\"isId\":false,\"isReadOnly\":false,\"hasDefaultValue\":false,\"type\":\"String\",\"isGenerated\":false,\"isUpdatedAt\":false},{\"name\":\"firstName\",\"kind\":\"scalar\",\"isList\":false,\"isRequired\":true,\"isUnique\":false,\"isId\":false,\"isReadOnly\":false,\"hasDefaultValue\":false,\"type\":\"String\",\"isGenerated\":false,\"isUpdatedAt\":false},{\"name\":\"lastName\",\"kind\":\"scalar\",\"isList\":false,\"isRequired\":true,\"isUnique\":false,\"isId\":false,\"isReadOnly\":false,\"hasDefaultValue\":false,\"type\":\"String\",\"isGenerated\":false,\"isUpdatedAt\":false},{\"name\":\"isActive\",\"kind\":\"scalar\",\"isList\":false,\"isRequired\":true,\"isUnique\":false,\"isId\":false,\"isReadOnly\":false,\"hasDefaultValue\":true,\"type\":\"Boolean\",\"default\":true,\"isGenerated\":false,\"isUpdatedAt\":false},{\"name\":\"customerId\",\"kind\":\"scalar\",\"isList\":false,\"isRequired\":false,\"isUnique\":true,\"isId\":false,\"isReadOnly\":true,\"hasDefaultValue\":false,\"type\":\"Int\",\"isGenerated\":false,\"isUpdatedAt\":false},{\"name\":\"customer\",\"kind\":\"object\",\"isList\":false,\"isRequired\":false,\"isUnique\":false,\"isId\":false,\"isReadOnly\":false,\"hasDefaultValue\":false,\"type\":\"Customer\",\"relationName\":\"CustomerToUser\",\"relationFromFields\":[\"customerId\"],\"relationToFields\":[\"id\"],\"isGenerated\":false,\"isUpdatedAt\":false},{\"name\":\"roles\",\"kind\":\"object\",\"isList\":true,\"isRequired\":true,\"isUnique\":false,\"isId\":false,\"isReadOnly\":false,\"hasDefaultValue\":false,\"type\":\"UserRole\",\"relationName\":\"UserToUserRole\",\"relationFromFields\":[],\"relationToFields\":[],\"isGenerated\":false,\"isUpdatedAt\":false},{\"name\":\"createdAt\",\"kind\":\"scalar\",\"isList\":false,\"isRequired\":true,\"isUnique\":false,\"isId\":false,\"isReadOnly\":false,\"hasDefaultValue\":true,\"type\":\"DateTime\",\"default\":{\"name\":\"now\",\"args\":[]},\"isGenerated\":false,\"isUpdatedAt\":false},{\"name\":\"updatedAt\",\"kind\":\"scalar\",\"isList\":false,\"isRequired\":true,\"isUnique\":false,\"isId\":false,\"isReadOnly\":false,\"hasDefaultValue\":false,\"type\":\"DateTime\",\"isGenerated\":false,\"isUpdatedAt\":true}],\"primaryKey\":null,\"uniqueFields\":[],\"uniqueIndexes\":[],\"isGenerated\":false},\"Role\":{\"dbName\":null,\"fields\":[{\"name\":\"id\",\"kind\":\"scalar\",\"isList\":false,\"isRequired\":true,\"isUnique\":false,\"isId\":true,\"isReadOnly\":false,\"hasDefaultValue\":true,\"type\":\"Int\",\"default\":{\"name\":\"autoincrement\",\"args\":[]},\"isGenerated\":false,\"isUpdatedAt\":false},{\"name\":\"name\",\"kind\":\"scalar\",\"isList\":false,\"isRequired\":true,\"isUnique\":true,\"isId\":false,\"isReadOnly\":false,\"hasDefaultValue\":false,\"type\":\"String\",\"isGenerated\":false,\"isUpdatedAt\":false},{\"name\":\"description\",\"kind\":\"scalar\",\"isList\":false,\"isRequired\":false,\"isUnique\":false,\"isId\":false,\"isReadOnly\":false,\"hasDefaultValue\":false,\"type\":\"String\",\"isGenerated\":false,\"isUpdatedAt\":false},{\"name\":\"permissions\",\"kind\":\"object\",\"isList\":true,\"isRequired\":true,\"isUnique\":false,\"isId\":false,\"isReadOnly\":false,\"hasDefaultValue\":false,\"type\":\"RolePermission\",\"relationName\":\"RoleToRolePermission\",\"relationFromFields\":[],\"relationToFields\":[],\"isGenerated\":false,\"isUpdatedAt\":false},{\"name\":\"users\",\"kind\":\"object\",\"isList\":true,\"isRequired\":true,\"isUnique\":false,\"isId\":false,\"isReadOnly\":false,\"hasDefaultValue\":false,\"type\":\"UserRole\",\"relationName\":\"RoleToUserRole\",\"relationFromFields\":[],\"relationToFields\":[],\"isGenerated\":false,\"isUpdatedAt\":false},{\"name\":\"createdAt\",\"kind\":\"scalar\",\"isList\":false,\"isRequired\":true,\"isUnique\":false,\"isId\":false,\"isReadOnly\":false,\"hasDefaultValue\":true,\"type\":\"DateTime\",\"default\":{\"name\":\"now\",\"args\":[]},\"isGenerated\":false,\"isUpdatedAt\":false},{\"name\":\"updatedAt\",\"kind\":\"scalar\",\"isList\":false,\"isRequired\":true,\"isUnique\":false,\"isId\":false,\"isReadOnly\":false,\"hasDefaultValue\":false,\"type\":\"DateTime\",\"isGenerated\":false,\"isUpdatedAt\":true}],\"primaryKey\":null,\"uniqueFields\":[],\"uniqueIndexes\":[],\"isGenerated\":false},\"Permission\":{\"dbName\":null,\"fields\":[{\"name\":\"id\",\"kind\":\"scalar\",\"isList\":false,\"isRequired\":true,\"isUnique\":false,\"isId\":true,\"isReadOnly\":false,\"hasDefaultValue\":true,\"type\":\"Int\",\"default\":{\"name\":\"autoincrement\",\"args\":[]},\"isGenerated\":false,\"isUpdatedAt\":false},{\"name\":\"resource\",\"kind\":\"scalar\",\"isList\":false,\"isRequired\":true,\"isUnique\":false,\"isId\":false,\"isReadOnly\":false,\"hasDefaultValue\":false,\"type\":\"String\",\"isGenerated\":false,\"isUpdatedAt\":false},{\"name\":\"action\",\"kind\":\"scalar\",\"isList\":false,\"isRequired\":true,\"isUnique\":false,\"isId\":false,\"isReadOnly\":false,\"hasDefaultValue\":false,\"type\":\"String\",\"isGenerated\":false,\"isUpdatedAt\":false},{\"name\":\"roles\",\"kind\":\"object\",\"isList\":true,\"isRequired\":true,\"isUnique\":false,\"isId\":false,\"isReadOnly\":false,\"hasDefaultValue\":false,\"type\":\"RolePermission\",\"relationName\":\"PermissionToRolePermission\",\"relationFromFields\":[],\"relationToFields\":[],\"isGenerated\":false,\"isUpdatedAt\":false}],\"primaryKey\":null,\"uniqueFields\":[[\"resource\",\"action\"]],\"uniqueIndexes\":[{\"name\":null,\"fields\":[\"resource\",\"action\"]}],\"isGenerated\":false},\"RolePermission\":{\"dbName\":null,\"fields\":[{\"name\":\"roleId\",\"kind\":\"scalar\",\"isList\":false,\"isRequired\":true,\"isUnique\":false,\"isId\":false,\"isReadOnly\":true,\"hasDefaultValue\":false,\"type\":\"Int\",\"isGenerated\":false,\"isUpdatedAt\":false},{\"name\":\"permissionId\",\"kind\":\"scalar\",\"isList\":false,\"isRequired\":true,\"isUnique\":false,\"isId\":false,\"isReadOnly\":true,\"hasDefaultValue\":false,\"type\":\"Int\",\"isGenerated\":false,\"isUpdatedAt\":false},{\"name\":\"role\",\"kind\":\"object\",\"isList\":false,\"isRequired\":true,\"isUnique\":false,\"isId\":false,\"isReadOnly\":false,\"hasDefaultValue\":false,\"type\":\"Role\",\"relationName\":\"RoleToRolePermission\",\"relationFromFields\":[\"roleId\"],\"relationToFields\":[\"id\"],\"relationOnDelete\":\"Cascade\",\"isGenerated\":false,\"isUpdatedAt\":false},{\"name\":\"permission\",\"kind\":\"object\",\"isList\":false,\"isRequired\":true,\"isUnique\":false,\"isId\":false,\"isReadOnly\":false,\"hasDefaultValue\":false,\"type\":\"Permission\",\"relationName\":\"PermissionToRolePermission\",\"relationFromFields\":[\"permissionId\"],\"relationToFields\":[\"id\"],\"relationOnDelete\":\"Cascade\",\"isGenerated\":false,\"isUpdatedAt\":false}],\"primaryKey\":{\"name\":null,\"fields\":[\"roleId\",\"permissionId\"]},\"uniqueFields\":[],\"uniqueIndexes\":[],\"isGenerated\":false},\"UserRole\":{\"dbName\":null,\"fields\":[{\"name\":\"userId\",\"kind\":\"scalar\",\"isList\":false,\"isRequired\":true,\"isUnique\":false,\"isId\":false,\"isReadOnly\":true,\"hasDefaultValue\":false,\"type\":\"Int\",\"isGenerated\":false,\"isUpdatedAt\":false},{\"name\":\"roleId\",\"kind\":\"scalar\",\"isList\":false,\"isRequired\":true,\"isUnique\":false,\"isId\":false,\"isReadOnly\":true,\"hasDefaultValue\":false,\"type\":\"Int\",\"isGenerated\":false,\"isUpdatedAt\":false},{\"name\":\"user\",\"kind\":\"object\",\"isList\":false,\"isRequired\":true,\"isUnique\":false,\"isId\":false,\"isReadOnly\":false,\"hasDefaultValue\":false,\"type\":\"User\",\"relationName\":\"UserToUserRole\",\"relationFromFields\":[\"userId\"],\"relationToFields\":[\"id\"],\"relationOnDelete\":\"Cascade\",\"isGenerated\":false,\"isUpdatedAt\":false},{\"name\":\"role\",\"kind\":\"object\",\"isList\":false,\"isRequired\":true,\"isUnique\":false,\"isId\":false,\"isReadOnly\":false,\"hasDefaultValue\":false,\"type\":\"Role\",\"relationName\":\"RoleToUserRole\",\"relationFromFields\":[\"roleId\"],\"relationToFields\":[\"id\"],\"relationOnDelete\":\"Cascade\",\"isGenerated\":false,\"isUpdatedAt\":false}],\"primaryKey\":{\"name\":null,\"fields\":[\"userId\",\"roleId\"]},\"uniqueFields\":[],\"uniqueIndexes\":[],\"isGenerated\":false},\"Customer\":{\"dbName\":null,\"fields\":[{\"name\":\"id\",\"kind\":\"scalar\",\"isList\":false,\"isRequired\":true,\"isUnique\":false,\"isId\":true,\"isReadOnly\":false,\"hasDefaultValue\":true,\"type\":\"Int\",\"default\":{\"name\":\"autoincrement\",\"args\":[]},\"isGenerated\":false,\"isUpdatedAt\":false},{\"name\":\"customerNumber\",\"kind\":\"scalar\",\"isList\":false,\"isRequired\":true,\"isUnique\":true,\"isId\":false,\"isReadOnly\":false,\"hasDefaultValue\":false,\"type\":\"String\",\"isGenerated\":false,\"isUpdatedAt\":false},{\"name\":\"type\",\"kind\":\"enum\",\"isList\":false,\"isRequired\":true,\"isUnique\":false,\"isId\":false,\"isReadOnly\":false,\"hasDefaultValue\":true,\"type\":\"CustomerType\",\"default\":\"PRIVATE\",\"isGenerated\":false,\"isUpdatedAt\":false},{\"name\":\"salutation\",\"kind\":\"scalar\",\"isList\":false,\"isRequired\":false,\"isUnique\":false,\"isId\":false,\"isReadOnly\":false,\"hasDefaultValue\":false,\"type\":\"String\",\"isGenerated\":false,\"isUpdatedAt\":false},{\"name\":\"firstName\",\"kind\":\"scalar\",\"isList\":false,\"isRequired\":true,\"isUnique\":false,\"isId\":false,\"isReadOnly\":false,\"hasDefaultValue\":false,\"type\":\"String\",\"isGenerated\":false,\"isUpdatedAt\":false},{\"name\":\"lastName\",\"kind\":\"scalar\",\"isList\":false,\"isRequired\":true,\"isUnique\":false,\"isId\":false,\"isReadOnly\":false,\"hasDefaultValue\":false,\"type\":\"String\",\"isGenerated\":false,\"isUpdatedAt\":false},{\"name\":\"companyName\",\"kind\":\"scalar\",\"isList\":false,\"isRequired\":false,\"isUnique\":false,\"isId\":false,\"isReadOnly\":false,\"hasDefaultValue\":false,\"type\":\"String\",\"isGenerated\":false,\"isUpdatedAt\":false},{\"name\":\"foundingDate\",\"kind\":\"scalar\",\"isList\":false,\"isRequired\":false,\"isUnique\":false,\"isId\":false,\"isReadOnly\":false,\"hasDefaultValue\":false,\"type\":\"DateTime\",\"isGenerated\":false,\"isUpdatedAt\":false},{\"name\":\"birthDate\",\"kind\":\"scalar\",\"isList\":false,\"isRequired\":false,\"isUnique\":false,\"isId\":false,\"isReadOnly\":false,\"hasDefaultValue\":false,\"type\":\"DateTime\",\"isGenerated\":false,\"isUpdatedAt\":false},{\"name\":\"birthPlace\",\"kind\":\"scalar\",\"isList\":false,\"isRequired\":false,\"isUnique\":false,\"isId\":false,\"isReadOnly\":false,\"hasDefaultValue\":false,\"type\":\"String\",\"isGenerated\":false,\"isUpdatedAt\":false},{\"name\":\"email\",\"kind\":\"scalar\",\"isList\":false,\"isRequired\":false,\"isUnique\":false,\"isId\":false,\"isReadOnly\":false,\"hasDefaultValue\":false,\"type\":\"String\",\"isGenerated\":false,\"isUpdatedAt\":false},{\"name\":\"phone\",\"kind\":\"scalar\",\"isList\":false,\"isRequired\":false,\"isUnique\":false,\"isId\":false,\"isReadOnly\":false,\"hasDefaultValue\":false,\"type\":\"String\",\"isGenerated\":false,\"isUpdatedAt\":false},{\"name\":\"mobile\",\"kind\":\"scalar\",\"isList\":false,\"isRequired\":false,\"isUnique\":false,\"isId\":false,\"isReadOnly\":false,\"hasDefaultValue\":false,\"type\":\"String\",\"isGenerated\":false,\"isUpdatedAt\":false},{\"name\":\"taxNumber\",\"kind\":\"scalar\",\"isList\":false,\"isRequired\":false,\"isUnique\":false,\"isId\":false,\"isReadOnly\":false,\"hasDefaultValue\":false,\"type\":\"String\",\"isGenerated\":false,\"isUpdatedAt\":false},{\"name\":\"businessRegistrationPath\",\"kind\":\"scalar\",\"isList\":false,\"isRequired\":false,\"isUnique\":false,\"isId\":false,\"isReadOnly\":false,\"hasDefaultValue\":false,\"type\":\"String\",\"isGenerated\":false,\"isUpdatedAt\":false},{\"name\":\"commercialRegisterPath\",\"kind\":\"scalar\",\"isList\":false,\"isRequired\":false,\"isUnique\":false,\"isId\":false,\"isReadOnly\":false,\"hasDefaultValue\":false,\"type\":\"String\",\"isGenerated\":false,\"isUpdatedAt\":false},{\"name\":\"commercialRegisterNumber\",\"kind\":\"scalar\",\"isList\":false,\"isRequired\":false,\"isUnique\":false,\"isId\":false,\"isReadOnly\":false,\"hasDefaultValue\":false,\"type\":\"String\",\"isGenerated\":false,\"isUpdatedAt\":false},{\"name\":\"privacyPolicyPath\",\"kind\":\"scalar\",\"isList\":false,\"isRequired\":false,\"isUnique\":false,\"isId\":false,\"isReadOnly\":false,\"hasDefaultValue\":false,\"type\":\"String\",\"isGenerated\":false,\"isUpdatedAt\":false},{\"name\":\"notes\",\"kind\":\"scalar\",\"isList\":false,\"isRequired\":false,\"isUnique\":false,\"isId\":false,\"isReadOnly\":false,\"hasDefaultValue\":false,\"type\":\"String\",\"isGenerated\":false,\"isUpdatedAt\":false},{\"name\":\"portalEnabled\",\"kind\":\"scalar\",\"isList\":false,\"isRequired\":true,\"isUnique\":false,\"isId\":false,\"isReadOnly\":false,\"hasDefaultValue\":true,\"type\":\"Boolean\",\"default\":false,\"isGenerated\":false,\"isUpdatedAt\":false},{\"name\":\"portalEmail\",\"kind\":\"scalar\",\"isList\":false,\"isRequired\":false,\"isUnique\":true,\"isId\":false,\"isReadOnly\":false,\"hasDefaultValue\":false,\"type\":\"String\",\"isGenerated\":false,\"isUpdatedAt\":false},{\"name\":\"portalPasswordHash\",\"kind\":\"scalar\",\"isList\":false,\"isRequired\":false,\"isUnique\":false,\"isId\":false,\"isReadOnly\":false,\"hasDefaultValue\":false,\"type\":\"String\",\"isGenerated\":false,\"isUpdatedAt\":false},{\"name\":\"portalPasswordEncrypted\",\"kind\":\"scalar\",\"isList\":false,\"isRequired\":false,\"isUnique\":false,\"isId\":false,\"isReadOnly\":false,\"hasDefaultValue\":false,\"type\":\"String\",\"isGenerated\":false,\"isUpdatedAt\":false},{\"name\":\"portalLastLogin\",\"kind\":\"scalar\",\"isList\":false,\"isRequired\":false,\"isUnique\":false,\"isId\":false,\"isReadOnly\":false,\"hasDefaultValue\":false,\"type\":\"DateTime\",\"isGenerated\":false,\"isUpdatedAt\":false},{\"name\":\"user\",\"kind\":\"object\",\"isList\":false,\"isRequired\":false,\"isUnique\":false,\"isId\":false,\"isReadOnly\":false,\"hasDefaultValue\":false,\"type\":\"User\",\"relationName\":\"CustomerToUser\",\"relationFromFields\":[],\"relationToFields\":[],\"isGenerated\":false,\"isUpdatedAt\":false},{\"name\":\"addresses\",\"kind\":\"object\",\"isList\":true,\"isRequired\":true,\"isUnique\":false,\"isId\":false,\"isReadOnly\":false,\"hasDefaultValue\":false,\"type\":\"Address\",\"relationName\":\"AddressToCustomer\",\"relationFromFields\":[],\"relationToFields\":[],\"isGenerated\":false,\"isUpdatedAt\":false},{\"name\":\"bankCards\",\"kind\":\"object\",\"isList\":true,\"isRequired\":true,\"isUnique\":false,\"isId\":false,\"isReadOnly\":false,\"hasDefaultValue\":false,\"type\":\"BankCard\",\"relationName\":\"BankCardToCustomer\",\"relationFromFields\":[],\"relationToFields\":[],\"isGenerated\":false,\"isUpdatedAt\":false},{\"name\":\"identityDocuments\",\"kind\":\"object\",\"isList\":true,\"isRequired\":true,\"isUnique\":false,\"isId\":false,\"isReadOnly\":false,\"hasDefaultValue\":false,\"type\":\"IdentityDocument\",\"relationName\":\"CustomerToIdentityDocument\",\"relationFromFields\":[],\"relationToFields\":[],\"isGenerated\":false,\"isUpdatedAt\":false},{\"name\":\"meters\",\"kind\":\"object\",\"isList\":true,\"isRequired\":true,\"isUnique\":false,\"isId\":false,\"isReadOnly\":false,\"hasDefaultValue\":false,\"type\":\"Meter\",\"relationName\":\"CustomerToMeter\",\"relationFromFields\":[],\"relationToFields\":[],\"isGenerated\":false,\"isUpdatedAt\":false},{\"name\":\"stressfreiEmails\",\"kind\":\"object\",\"isList\":true,\"isRequired\":true,\"isUnique\":false,\"isId\":false,\"isReadOnly\":false,\"hasDefaultValue\":false,\"type\":\"StressfreiEmail\",\"relationName\":\"CustomerToStressfreiEmail\",\"relationFromFields\":[],\"relationToFields\":[],\"isGenerated\":false,\"isUpdatedAt\":false},{\"name\":\"contracts\",\"kind\":\"object\",\"isList\":true,\"isRequired\":true,\"isUnique\":false,\"isId\":false,\"isReadOnly\":false,\"hasDefaultValue\":false,\"type\":\"Contract\",\"relationName\":\"ContractToCustomer\",\"relationFromFields\":[],\"relationToFields\":[],\"isGenerated\":false,\"isUpdatedAt\":false},{\"name\":\"representingFor\",\"kind\":\"object\",\"isList\":true,\"isRequired\":true,\"isUnique\":false,\"isId\":false,\"isReadOnly\":false,\"hasDefaultValue\":false,\"type\":\"CustomerRepresentative\",\"relationName\":\"RepresentativeCustomer\",\"relationFromFields\":[],\"relationToFields\":[],\"isGenerated\":false,\"isUpdatedAt\":false},{\"name\":\"representedBy\",\"kind\":\"object\",\"isList\":true,\"isRequired\":true,\"isUnique\":false,\"isId\":false,\"isReadOnly\":false,\"hasDefaultValue\":false,\"type\":\"CustomerRepresentative\",\"relationName\":\"RepresentedCustomer\",\"relationFromFields\":[],\"relationToFields\":[],\"isGenerated\":false,\"isUpdatedAt\":false},{\"name\":\"createdAt\",\"kind\":\"scalar\",\"isList\":false,\"isRequired\":true,\"isUnique\":false,\"isId\":false,\"isReadOnly\":false,\"hasDefaultValue\":true,\"type\":\"DateTime\",\"default\":{\"name\":\"now\",\"args\":[]},\"isGenerated\":false,\"isUpdatedAt\":false},{\"name\":\"updatedAt\",\"kind\":\"scalar\",\"isList\":false,\"isRequired\":true,\"isUnique\":false,\"isId\":false,\"isReadOnly\":false,\"hasDefaultValue\":false,\"type\":\"DateTime\",\"isGenerated\":false,\"isUpdatedAt\":true}],\"primaryKey\":null,\"uniqueFields\":[],\"uniqueIndexes\":[],\"isGenerated\":false},\"CustomerRepresentative\":{\"dbName\":null,\"fields\":[{\"name\":\"id\",\"kind\":\"scalar\",\"isList\":false,\"isRequired\":true,\"isUnique\":false,\"isId\":true,\"isReadOnly\":false,\"hasDefaultValue\":true,\"type\":\"Int\",\"default\":{\"name\":\"autoincrement\",\"args\":[]},\"isGenerated\":false,\"isUpdatedAt\":false},{\"name\":\"customerId\",\"kind\":\"scalar\",\"isList\":false,\"isRequired\":true,\"isUnique\":false,\"isId\":false,\"isReadOnly\":true,\"hasDefaultValue\":false,\"type\":\"Int\",\"isGenerated\":false,\"isUpdatedAt\":false},{\"name\":\"customer\",\"kind\":\"object\",\"isList\":false,\"isRequired\":true,\"isUnique\":false,\"isId\":false,\"isReadOnly\":false,\"hasDefaultValue\":false,\"type\":\"Customer\",\"relationName\":\"RepresentedCustomer\",\"relationFromFields\":[\"customerId\"],\"relationToFields\":[\"id\"],\"relationOnDelete\":\"Cascade\",\"isGenerated\":false,\"isUpdatedAt\":false},{\"name\":\"representativeId\",\"kind\":\"scalar\",\"isList\":false,\"isRequired\":true,\"isUnique\":false,\"isId\":false,\"isReadOnly\":true,\"hasDefaultValue\":false,\"type\":\"Int\",\"isGenerated\":false,\"isUpdatedAt\":false},{\"name\":\"representative\",\"kind\":\"object\",\"isList\":false,\"isRequired\":true,\"isUnique\":false,\"isId\":false,\"isReadOnly\":false,\"hasDefaultValue\":false,\"type\":\"Customer\",\"relationName\":\"RepresentativeCustomer\",\"relationFromFields\":[\"representativeId\"],\"relationToFields\":[\"id\"],\"relationOnDelete\":\"Cascade\",\"isGenerated\":false,\"isUpdatedAt\":false},{\"name\":\"notes\",\"kind\":\"scalar\",\"isList\":false,\"isRequired\":false,\"isUnique\":false,\"isId\":false,\"isReadOnly\":false,\"hasDefaultValue\":false,\"type\":\"String\",\"isGenerated\":false,\"isUpdatedAt\":false},{\"name\":\"isActive\",\"kind\":\"scalar\",\"isList\":false,\"isRequired\":true,\"isUnique\":false,\"isId\":false,\"isReadOnly\":false,\"hasDefaultValue\":true,\"type\":\"Boolean\",\"default\":true,\"isGenerated\":false,\"isUpdatedAt\":false},{\"name\":\"createdAt\",\"kind\":\"scalar\",\"isList\":false,\"isRequired\":true,\"isUnique\":false,\"isId\":false,\"isReadOnly\":false,\"hasDefaultValue\":true,\"type\":\"DateTime\",\"default\":{\"name\":\"now\",\"args\":[]},\"isGenerated\":false,\"isUpdatedAt\":false},{\"name\":\"updatedAt\",\"kind\":\"scalar\",\"isList\":false,\"isRequired\":true,\"isUnique\":false,\"isId\":false,\"isReadOnly\":false,\"hasDefaultValue\":false,\"type\":\"DateTime\",\"isGenerated\":false,\"isUpdatedAt\":true}],\"primaryKey\":null,\"uniqueFields\":[[\"customerId\",\"representativeId\"]],\"uniqueIndexes\":[{\"name\":null,\"fields\":[\"customerId\",\"representativeId\"]}],\"isGenerated\":false},\"Address\":{\"dbName\":null,\"fields\":[{\"name\":\"id\",\"kind\":\"scalar\",\"isList\":false,\"isRequired\":true,\"isUnique\":false,\"isId\":true,\"isReadOnly\":false,\"hasDefaultValue\":true,\"type\":\"Int\",\"default\":{\"name\":\"autoincrement\",\"args\":[]},\"isGenerated\":false,\"isUpdatedAt\":false},{\"name\":\"customerId\",\"kind\":\"scalar\",\"isList\":false,\"isRequired\":true,\"isUnique\":false,\"isId\":false,\"isReadOnly\":true,\"hasDefaultValue\":false,\"type\":\"Int\",\"isGenerated\":false,\"isUpdatedAt\":false},{\"name\":\"customer\",\"kind\":\"object\",\"isList\":false,\"isRequired\":true,\"isUnique\":false,\"isId\":false,\"isReadOnly\":false,\"hasDefaultValue\":false,\"type\":\"Customer\",\"relationName\":\"AddressToCustomer\",\"relationFromFields\":[\"customerId\"],\"relationToFields\":[\"id\"],\"relationOnDelete\":\"Cascade\",\"isGenerated\":false,\"isUpdatedAt\":false},{\"name\":\"type\",\"kind\":\"enum\",\"isList\":false,\"isRequired\":true,\"isUnique\":false,\"isId\":false,\"isReadOnly\":false,\"hasDefaultValue\":true,\"type\":\"AddressType\",\"default\":\"DELIVERY_RESIDENCE\",\"isGenerated\":false,\"isUpdatedAt\":false},{\"name\":\"street\",\"kind\":\"scalar\",\"isList\":false,\"isRequired\":true,\"isUnique\":false,\"isId\":false,\"isReadOnly\":false,\"hasDefaultValue\":false,\"type\":\"String\",\"isGenerated\":false,\"isUpdatedAt\":false},{\"name\":\"houseNumber\",\"kind\":\"scalar\",\"isList\":false,\"isRequired\":true,\"isUnique\":false,\"isId\":false,\"isReadOnly\":false,\"hasDefaultValue\":false,\"type\":\"String\",\"isGenerated\":false,\"isUpdatedAt\":false},{\"name\":\"postalCode\",\"kind\":\"scalar\",\"isList\":false,\"isRequired\":true,\"isUnique\":false,\"isId\":false,\"isReadOnly\":false,\"hasDefaultValue\":false,\"type\":\"String\",\"isGenerated\":false,\"isUpdatedAt\":false},{\"name\":\"city\",\"kind\":\"scalar\",\"isList\":false,\"isRequired\":true,\"isUnique\":false,\"isId\":false,\"isReadOnly\":false,\"hasDefaultValue\":false,\"type\":\"String\",\"isGenerated\":false,\"isUpdatedAt\":false},{\"name\":\"country\",\"kind\":\"scalar\",\"isList\":false,\"isRequired\":true,\"isUnique\":false,\"isId\":false,\"isReadOnly\":false,\"hasDefaultValue\":true,\"type\":\"String\",\"default\":\"Deutschland\",\"isGenerated\":false,\"isUpdatedAt\":false},{\"name\":\"isDefault\",\"kind\":\"scalar\",\"isList\":false,\"isRequired\":true,\"isUnique\":false,\"isId\":false,\"isReadOnly\":false,\"hasDefaultValue\":true,\"type\":\"Boolean\",\"default\":false,\"isGenerated\":false,\"isUpdatedAt\":false},{\"name\":\"contracts\",\"kind\":\"object\",\"isList\":true,\"isRequired\":true,\"isUnique\":false,\"isId\":false,\"isReadOnly\":false,\"hasDefaultValue\":false,\"type\":\"Contract\",\"relationName\":\"AddressToContract\",\"relationFromFields\":[],\"relationToFields\":[],\"isGenerated\":false,\"isUpdatedAt\":false},{\"name\":\"createdAt\",\"kind\":\"scalar\",\"isList\":false,\"isRequired\":true,\"isUnique\":false,\"isId\":false,\"isReadOnly\":false,\"hasDefaultValue\":true,\"type\":\"DateTime\",\"default\":{\"name\":\"now\",\"args\":[]},\"isGenerated\":false,\"isUpdatedAt\":false},{\"name\":\"updatedAt\",\"kind\":\"scalar\",\"isList\":false,\"isRequired\":true,\"isUnique\":false,\"isId\":false,\"isReadOnly\":false,\"hasDefaultValue\":false,\"type\":\"DateTime\",\"isGenerated\":false,\"isUpdatedAt\":true}],\"primaryKey\":null,\"uniqueFields\":[],\"uniqueIndexes\":[],\"isGenerated\":false},\"BankCard\":{\"dbName\":null,\"fields\":[{\"name\":\"id\",\"kind\":\"scalar\",\"isList\":false,\"isRequired\":true,\"isUnique\":false,\"isId\":true,\"isReadOnly\":false,\"hasDefaultValue\":true,\"type\":\"Int\",\"default\":{\"name\":\"autoincrement\",\"args\":[]},\"isGenerated\":false,\"isUpdatedAt\":false},{\"name\":\"customerId\",\"kind\":\"scalar\",\"isList\":false,\"isRequired\":true,\"isUnique\":false,\"isId\":false,\"isReadOnly\":true,\"hasDefaultValue\":false,\"type\":\"Int\",\"isGenerated\":false,\"isUpdatedAt\":false},{\"name\":\"customer\",\"kind\":\"object\",\"isList\":false,\"isRequired\":true,\"isUnique\":false,\"isId\":false,\"isReadOnly\":false,\"hasDefaultValue\":false,\"type\":\"Customer\",\"relationName\":\"BankCardToCustomer\",\"relationFromFields\":[\"customerId\"],\"relationToFields\":[\"id\"],\"relationOnDelete\":\"Cascade\",\"isGenerated\":false,\"isUpdatedAt\":false},{\"name\":\"accountHolder\",\"kind\":\"scalar\",\"isList\":false,\"isRequired\":true,\"isUnique\":false,\"isId\":false,\"isReadOnly\":false,\"hasDefaultValue\":false,\"type\":\"String\",\"isGenerated\":false,\"isUpdatedAt\":false},{\"name\":\"iban\",\"kind\":\"scalar\",\"isList\":false,\"isRequired\":true,\"isUnique\":false,\"isId\":false,\"isReadOnly\":false,\"hasDefaultValue\":false,\"type\":\"String\",\"isGenerated\":false,\"isUpdatedAt\":false},{\"name\":\"bic\",\"kind\":\"scalar\",\"isList\":false,\"isRequired\":false,\"isUnique\":false,\"isId\":false,\"isReadOnly\":false,\"hasDefaultValue\":false,\"type\":\"String\",\"isGenerated\":false,\"isUpdatedAt\":false},{\"name\":\"bankName\",\"kind\":\"scalar\",\"isList\":false,\"isRequired\":false,\"isUnique\":false,\"isId\":false,\"isReadOnly\":false,\"hasDefaultValue\":false,\"type\":\"String\",\"isGenerated\":false,\"isUpdatedAt\":false},{\"name\":\"expiryDate\",\"kind\":\"scalar\",\"isList\":false,\"isRequired\":false,\"isUnique\":false,\"isId\":false,\"isReadOnly\":false,\"hasDefaultValue\":false,\"type\":\"DateTime\",\"isGenerated\":false,\"isUpdatedAt\":false},{\"name\":\"documentPath\",\"kind\":\"scalar\",\"isList\":false,\"isRequired\":false,\"isUnique\":false,\"isId\":false,\"isReadOnly\":false,\"hasDefaultValue\":false,\"type\":\"String\",\"isGenerated\":false,\"isUpdatedAt\":false},{\"name\":\"isActive\",\"kind\":\"scalar\",\"isList\":false,\"isRequired\":true,\"isUnique\":false,\"isId\":false,\"isReadOnly\":false,\"hasDefaultValue\":true,\"type\":\"Boolean\",\"default\":true,\"isGenerated\":false,\"isUpdatedAt\":false},{\"name\":\"contracts\",\"kind\":\"object\",\"isList\":true,\"isRequired\":true,\"isUnique\":false,\"isId\":false,\"isReadOnly\":false,\"hasDefaultValue\":false,\"type\":\"Contract\",\"relationName\":\"BankCardToContract\",\"relationFromFields\":[],\"relationToFields\":[],\"isGenerated\":false,\"isUpdatedAt\":false},{\"name\":\"createdAt\",\"kind\":\"scalar\",\"isList\":false,\"isRequired\":true,\"isUnique\":false,\"isId\":false,\"isReadOnly\":false,\"hasDefaultValue\":true,\"type\":\"DateTime\",\"default\":{\"name\":\"now\",\"args\":[]},\"isGenerated\":false,\"isUpdatedAt\":false},{\"name\":\"updatedAt\",\"kind\":\"scalar\",\"isList\":false,\"isRequired\":true,\"isUnique\":false,\"isId\":false,\"isReadOnly\":false,\"hasDefaultValue\":false,\"type\":\"DateTime\",\"isGenerated\":false,\"isUpdatedAt\":true}],\"primaryKey\":null,\"uniqueFields\":[],\"uniqueIndexes\":[],\"isGenerated\":false},\"IdentityDocument\":{\"dbName\":null,\"fields\":[{\"name\":\"id\",\"kind\":\"scalar\",\"isList\":false,\"isRequired\":true,\"isUnique\":false,\"isId\":true,\"isReadOnly\":false,\"hasDefaultValue\":true,\"type\":\"Int\",\"default\":{\"name\":\"autoincrement\",\"args\":[]},\"isGenerated\":false,\"isUpdatedAt\":false},{\"name\":\"customerId\",\"kind\":\"scalar\",\"isList\":false,\"isRequired\":true,\"isUnique\":false,\"isId\":false,\"isReadOnly\":true,\"hasDefaultValue\":false,\"type\":\"Int\",\"isGenerated\":false,\"isUpdatedAt\":false},{\"name\":\"customer\",\"kind\":\"object\",\"isList\":false,\"isRequired\":true,\"isUnique\":false,\"isId\":false,\"isReadOnly\":false,\"hasDefaultValue\":false,\"type\":\"Customer\",\"relationName\":\"CustomerToIdentityDocument\",\"relationFromFields\":[\"customerId\"],\"relationToFields\":[\"id\"],\"relationOnDelete\":\"Cascade\",\"isGenerated\":false,\"isUpdatedAt\":false},{\"name\":\"type\",\"kind\":\"enum\",\"isList\":false,\"isRequired\":true,\"isUnique\":false,\"isId\":false,\"isReadOnly\":false,\"hasDefaultValue\":true,\"type\":\"DocumentType\",\"default\":\"ID_CARD\",\"isGenerated\":false,\"isUpdatedAt\":false},{\"name\":\"documentNumber\",\"kind\":\"scalar\",\"isList\":false,\"isRequired\":true,\"isUnique\":false,\"isId\":false,\"isReadOnly\":false,\"hasDefaultValue\":false,\"type\":\"String\",\"isGenerated\":false,\"isUpdatedAt\":false},{\"name\":\"issuingAuthority\",\"kind\":\"scalar\",\"isList\":false,\"isRequired\":false,\"isUnique\":false,\"isId\":false,\"isReadOnly\":false,\"hasDefaultValue\":false,\"type\":\"String\",\"isGenerated\":false,\"isUpdatedAt\":false},{\"name\":\"issueDate\",\"kind\":\"scalar\",\"isList\":false,\"isRequired\":false,\"isUnique\":false,\"isId\":false,\"isReadOnly\":false,\"hasDefaultValue\":false,\"type\":\"DateTime\",\"isGenerated\":false,\"isUpdatedAt\":false},{\"name\":\"expiryDate\",\"kind\":\"scalar\",\"isList\":false,\"isRequired\":false,\"isUnique\":false,\"isId\":false,\"isReadOnly\":false,\"hasDefaultValue\":false,\"type\":\"DateTime\",\"isGenerated\":false,\"isUpdatedAt\":false},{\"name\":\"documentPath\",\"kind\":\"scalar\",\"isList\":false,\"isRequired\":false,\"isUnique\":false,\"isId\":false,\"isReadOnly\":false,\"hasDefaultValue\":false,\"type\":\"String\",\"isGenerated\":false,\"isUpdatedAt\":false},{\"name\":\"isActive\",\"kind\":\"scalar\",\"isList\":false,\"isRequired\":true,\"isUnique\":false,\"isId\":false,\"isReadOnly\":false,\"hasDefaultValue\":true,\"type\":\"Boolean\",\"default\":true,\"isGenerated\":false,\"isUpdatedAt\":false},{\"name\":\"licenseClasses\",\"kind\":\"scalar\",\"isList\":false,\"isRequired\":false,\"isUnique\":false,\"isId\":false,\"isReadOnly\":false,\"hasDefaultValue\":false,\"type\":\"String\",\"isGenerated\":false,\"isUpdatedAt\":false},{\"name\":\"licenseIssueDate\",\"kind\":\"scalar\",\"isList\":false,\"isRequired\":false,\"isUnique\":false,\"isId\":false,\"isReadOnly\":false,\"hasDefaultValue\":false,\"type\":\"DateTime\",\"isGenerated\":false,\"isUpdatedAt\":false},{\"name\":\"contracts\",\"kind\":\"object\",\"isList\":true,\"isRequired\":true,\"isUnique\":false,\"isId\":false,\"isReadOnly\":false,\"hasDefaultValue\":false,\"type\":\"Contract\",\"relationName\":\"ContractToIdentityDocument\",\"relationFromFields\":[],\"relationToFields\":[],\"isGenerated\":false,\"isUpdatedAt\":false},{\"name\":\"createdAt\",\"kind\":\"scalar\",\"isList\":false,\"isRequired\":true,\"isUnique\":false,\"isId\":false,\"isReadOnly\":false,\"hasDefaultValue\":true,\"type\":\"DateTime\",\"default\":{\"name\":\"now\",\"args\":[]},\"isGenerated\":false,\"isUpdatedAt\":false},{\"name\":\"updatedAt\",\"kind\":\"scalar\",\"isList\":false,\"isRequired\":true,\"isUnique\":false,\"isId\":false,\"isReadOnly\":false,\"hasDefaultValue\":false,\"type\":\"DateTime\",\"isGenerated\":false,\"isUpdatedAt\":true}],\"primaryKey\":null,\"uniqueFields\":[],\"uniqueIndexes\":[],\"isGenerated\":false},\"EmailProviderConfig\":{\"dbName\":null,\"fields\":[{\"name\":\"id\",\"kind\":\"scalar\",\"isList\":false,\"isRequired\":true,\"isUnique\":false,\"isId\":true,\"isReadOnly\":false,\"hasDefaultValue\":true,\"type\":\"Int\",\"default\":{\"name\":\"autoincrement\",\"args\":[]},\"isGenerated\":false,\"isUpdatedAt\":false},{\"name\":\"name\",\"kind\":\"scalar\",\"isList\":false,\"isRequired\":true,\"isUnique\":true,\"isId\":false,\"isReadOnly\":false,\"hasDefaultValue\":false,\"type\":\"String\",\"isGenerated\":false,\"isUpdatedAt\":false},{\"name\":\"type\",\"kind\":\"enum\",\"isList\":false,\"isRequired\":true,\"isUnique\":false,\"isId\":false,\"isReadOnly\":false,\"hasDefaultValue\":false,\"type\":\"EmailProviderType\",\"isGenerated\":false,\"isUpdatedAt\":false},{\"name\":\"apiUrl\",\"kind\":\"scalar\",\"isList\":false,\"isRequired\":true,\"isUnique\":false,\"isId\":false,\"isReadOnly\":false,\"hasDefaultValue\":false,\"type\":\"String\",\"isGenerated\":false,\"isUpdatedAt\":false},{\"name\":\"apiKey\",\"kind\":\"scalar\",\"isList\":false,\"isRequired\":false,\"isUnique\":false,\"isId\":false,\"isReadOnly\":false,\"hasDefaultValue\":false,\"type\":\"String\",\"isGenerated\":false,\"isUpdatedAt\":false},{\"name\":\"username\",\"kind\":\"scalar\",\"isList\":false,\"isRequired\":false,\"isUnique\":false,\"isId\":false,\"isReadOnly\":false,\"hasDefaultValue\":false,\"type\":\"String\",\"isGenerated\":false,\"isUpdatedAt\":false},{\"name\":\"passwordEncrypted\",\"kind\":\"scalar\",\"isList\":false,\"isRequired\":false,\"isUnique\":false,\"isId\":false,\"isReadOnly\":false,\"hasDefaultValue\":false,\"type\":\"String\",\"isGenerated\":false,\"isUpdatedAt\":false},{\"name\":\"domain\",\"kind\":\"scalar\",\"isList\":false,\"isRequired\":true,\"isUnique\":false,\"isId\":false,\"isReadOnly\":false,\"hasDefaultValue\":false,\"type\":\"String\",\"isGenerated\":false,\"isUpdatedAt\":false},{\"name\":\"defaultForwardEmail\",\"kind\":\"scalar\",\"isList\":false,\"isRequired\":false,\"isUnique\":false,\"isId\":false,\"isReadOnly\":false,\"hasDefaultValue\":false,\"type\":\"String\",\"isGenerated\":false,\"isUpdatedAt\":false},{\"name\":\"isActive\",\"kind\":\"scalar\",\"isList\":false,\"isRequired\":true,\"isUnique\":false,\"isId\":false,\"isReadOnly\":false,\"hasDefaultValue\":true,\"type\":\"Boolean\",\"default\":true,\"isGenerated\":false,\"isUpdatedAt\":false},{\"name\":\"isDefault\",\"kind\":\"scalar\",\"isList\":false,\"isRequired\":true,\"isUnique\":false,\"isId\":false,\"isReadOnly\":false,\"hasDefaultValue\":true,\"type\":\"Boolean\",\"default\":false,\"isGenerated\":false,\"isUpdatedAt\":false},{\"name\":\"createdAt\",\"kind\":\"scalar\",\"isList\":false,\"isRequired\":true,\"isUnique\":false,\"isId\":false,\"isReadOnly\":false,\"hasDefaultValue\":true,\"type\":\"DateTime\",\"default\":{\"name\":\"now\",\"args\":[]},\"isGenerated\":false,\"isUpdatedAt\":false},{\"name\":\"updatedAt\",\"kind\":\"scalar\",\"isList\":false,\"isRequired\":true,\"isUnique\":false,\"isId\":false,\"isReadOnly\":false,\"hasDefaultValue\":false,\"type\":\"DateTime\",\"isGenerated\":false,\"isUpdatedAt\":true}],\"primaryKey\":null,\"uniqueFields\":[],\"uniqueIndexes\":[],\"isGenerated\":false},\"StressfreiEmail\":{\"dbName\":null,\"fields\":[{\"name\":\"id\",\"kind\":\"scalar\",\"isList\":false,\"isRequired\":true,\"isUnique\":false,\"isId\":true,\"isReadOnly\":false,\"hasDefaultValue\":true,\"type\":\"Int\",\"default\":{\"name\":\"autoincrement\",\"args\":[]},\"isGenerated\":false,\"isUpdatedAt\":false},{\"name\":\"customerId\",\"kind\":\"scalar\",\"isList\":false,\"isRequired\":true,\"isUnique\":false,\"isId\":false,\"isReadOnly\":true,\"hasDefaultValue\":false,\"type\":\"Int\",\"isGenerated\":false,\"isUpdatedAt\":false},{\"name\":\"customer\",\"kind\":\"object\",\"isList\":false,\"isRequired\":true,\"isUnique\":false,\"isId\":false,\"isReadOnly\":false,\"hasDefaultValue\":false,\"type\":\"Customer\",\"relationName\":\"CustomerToStressfreiEmail\",\"relationFromFields\":[\"customerId\"],\"relationToFields\":[\"id\"],\"relationOnDelete\":\"Cascade\",\"isGenerated\":false,\"isUpdatedAt\":false},{\"name\":\"email\",\"kind\":\"scalar\",\"isList\":false,\"isRequired\":true,\"isUnique\":false,\"isId\":false,\"isReadOnly\":false,\"hasDefaultValue\":false,\"type\":\"String\",\"isGenerated\":false,\"isUpdatedAt\":false},{\"name\":\"platform\",\"kind\":\"scalar\",\"isList\":false,\"isRequired\":false,\"isUnique\":false,\"isId\":false,\"isReadOnly\":false,\"hasDefaultValue\":false,\"type\":\"String\",\"isGenerated\":false,\"isUpdatedAt\":false},{\"name\":\"notes\",\"kind\":\"scalar\",\"isList\":false,\"isRequired\":false,\"isUnique\":false,\"isId\":false,\"isReadOnly\":false,\"hasDefaultValue\":false,\"type\":\"String\",\"isGenerated\":false,\"isUpdatedAt\":false},{\"name\":\"isActive\",\"kind\":\"scalar\",\"isList\":false,\"isRequired\":true,\"isUnique\":false,\"isId\":false,\"isReadOnly\":false,\"hasDefaultValue\":true,\"type\":\"Boolean\",\"default\":true,\"isGenerated\":false,\"isUpdatedAt\":false},{\"name\":\"isProvisioned\",\"kind\":\"scalar\",\"isList\":false,\"isRequired\":true,\"isUnique\":false,\"isId\":false,\"isReadOnly\":false,\"hasDefaultValue\":true,\"type\":\"Boolean\",\"default\":false,\"isGenerated\":false,\"isUpdatedAt\":false},{\"name\":\"provisionedAt\",\"kind\":\"scalar\",\"isList\":false,\"isRequired\":false,\"isUnique\":false,\"isId\":false,\"isReadOnly\":false,\"hasDefaultValue\":false,\"type\":\"DateTime\",\"isGenerated\":false,\"isUpdatedAt\":false},{\"name\":\"provisionError\",\"kind\":\"scalar\",\"isList\":false,\"isRequired\":false,\"isUnique\":false,\"isId\":false,\"isReadOnly\":false,\"hasDefaultValue\":false,\"type\":\"String\",\"isGenerated\":false,\"isUpdatedAt\":false},{\"name\":\"contracts\",\"kind\":\"object\",\"isList\":true,\"isRequired\":true,\"isUnique\":false,\"isId\":false,\"isReadOnly\":false,\"hasDefaultValue\":false,\"type\":\"Contract\",\"relationName\":\"ContractToStressfreiEmail\",\"relationFromFields\":[],\"relationToFields\":[],\"isGenerated\":false,\"isUpdatedAt\":false},{\"name\":\"createdAt\",\"kind\":\"scalar\",\"isList\":false,\"isRequired\":true,\"isUnique\":false,\"isId\":false,\"isReadOnly\":false,\"hasDefaultValue\":true,\"type\":\"DateTime\",\"default\":{\"name\":\"now\",\"args\":[]},\"isGenerated\":false,\"isUpdatedAt\":false},{\"name\":\"updatedAt\",\"kind\":\"scalar\",\"isList\":false,\"isRequired\":true,\"isUnique\":false,\"isId\":false,\"isReadOnly\":false,\"hasDefaultValue\":false,\"type\":\"DateTime\",\"isGenerated\":false,\"isUpdatedAt\":true}],\"primaryKey\":null,\"uniqueFields\":[],\"uniqueIndexes\":[],\"isGenerated\":false},\"Meter\":{\"dbName\":null,\"fields\":[{\"name\":\"id\",\"kind\":\"scalar\",\"isList\":false,\"isRequired\":true,\"isUnique\":false,\"isId\":true,\"isReadOnly\":false,\"hasDefaultValue\":true,\"type\":\"Int\",\"default\":{\"name\":\"autoincrement\",\"args\":[]},\"isGenerated\":false,\"isUpdatedAt\":false},{\"name\":\"customerId\",\"kind\":\"scalar\",\"isList\":false,\"isRequired\":true,\"isUnique\":false,\"isId\":false,\"isReadOnly\":true,\"hasDefaultValue\":false,\"type\":\"Int\",\"isGenerated\":false,\"isUpdatedAt\":false},{\"name\":\"customer\",\"kind\":\"object\",\"isList\":false,\"isRequired\":true,\"isUnique\":false,\"isId\":false,\"isReadOnly\":false,\"hasDefaultValue\":false,\"type\":\"Customer\",\"relationName\":\"CustomerToMeter\",\"relationFromFields\":[\"customerId\"],\"relationToFields\":[\"id\"],\"relationOnDelete\":\"Cascade\",\"isGenerated\":false,\"isUpdatedAt\":false},{\"name\":\"meterNumber\",\"kind\":\"scalar\",\"isList\":false,\"isRequired\":true,\"isUnique\":false,\"isId\":false,\"isReadOnly\":false,\"hasDefaultValue\":false,\"type\":\"String\",\"isGenerated\":false,\"isUpdatedAt\":false},{\"name\":\"type\",\"kind\":\"enum\",\"isList\":false,\"isRequired\":true,\"isUnique\":false,\"isId\":false,\"isReadOnly\":false,\"hasDefaultValue\":false,\"type\":\"MeterType\",\"isGenerated\":false,\"isUpdatedAt\":false},{\"name\":\"location\",\"kind\":\"scalar\",\"isList\":false,\"isRequired\":false,\"isUnique\":false,\"isId\":false,\"isReadOnly\":false,\"hasDefaultValue\":false,\"type\":\"String\",\"isGenerated\":false,\"isUpdatedAt\":false},{\"name\":\"isActive\",\"kind\":\"scalar\",\"isList\":false,\"isRequired\":true,\"isUnique\":false,\"isId\":false,\"isReadOnly\":false,\"hasDefaultValue\":true,\"type\":\"Boolean\",\"default\":true,\"isGenerated\":false,\"isUpdatedAt\":false},{\"name\":\"readings\",\"kind\":\"object\",\"isList\":true,\"isRequired\":true,\"isUnique\":false,\"isId\":false,\"isReadOnly\":false,\"hasDefaultValue\":false,\"type\":\"MeterReading\",\"relationName\":\"MeterToMeterReading\",\"relationFromFields\":[],\"relationToFields\":[],\"isGenerated\":false,\"isUpdatedAt\":false},{\"name\":\"energyDetails\",\"kind\":\"object\",\"isList\":true,\"isRequired\":true,\"isUnique\":false,\"isId\":false,\"isReadOnly\":false,\"hasDefaultValue\":false,\"type\":\"EnergyContractDetails\",\"relationName\":\"EnergyContractDetailsToMeter\",\"relationFromFields\":[],\"relationToFields\":[],\"isGenerated\":false,\"isUpdatedAt\":false},{\"name\":\"createdAt\",\"kind\":\"scalar\",\"isList\":false,\"isRequired\":true,\"isUnique\":false,\"isId\":false,\"isReadOnly\":false,\"hasDefaultValue\":true,\"type\":\"DateTime\",\"default\":{\"name\":\"now\",\"args\":[]},\"isGenerated\":false,\"isUpdatedAt\":false},{\"name\":\"updatedAt\",\"kind\":\"scalar\",\"isList\":false,\"isRequired\":true,\"isUnique\":false,\"isId\":false,\"isReadOnly\":false,\"hasDefaultValue\":false,\"type\":\"DateTime\",\"isGenerated\":false,\"isUpdatedAt\":true}],\"primaryKey\":null,\"uniqueFields\":[],\"uniqueIndexes\":[],\"isGenerated\":false},\"MeterReading\":{\"dbName\":null,\"fields\":[{\"name\":\"id\",\"kind\":\"scalar\",\"isList\":false,\"isRequired\":true,\"isUnique\":false,\"isId\":true,\"isReadOnly\":false,\"hasDefaultValue\":true,\"type\":\"Int\",\"default\":{\"name\":\"autoincrement\",\"args\":[]},\"isGenerated\":false,\"isUpdatedAt\":false},{\"name\":\"meterId\",\"kind\":\"scalar\",\"isList\":false,\"isRequired\":true,\"isUnique\":false,\"isId\":false,\"isReadOnly\":true,\"hasDefaultValue\":false,\"type\":\"Int\",\"isGenerated\":false,\"isUpdatedAt\":false},{\"name\":\"meter\",\"kind\":\"object\",\"isList\":false,\"isRequired\":true,\"isUnique\":false,\"isId\":false,\"isReadOnly\":false,\"hasDefaultValue\":false,\"type\":\"Meter\",\"relationName\":\"MeterToMeterReading\",\"relationFromFields\":[\"meterId\"],\"relationToFields\":[\"id\"],\"relationOnDelete\":\"Cascade\",\"isGenerated\":false,\"isUpdatedAt\":false},{\"name\":\"readingDate\",\"kind\":\"scalar\",\"isList\":false,\"isRequired\":true,\"isUnique\":false,\"isId\":false,\"isReadOnly\":false,\"hasDefaultValue\":false,\"type\":\"DateTime\",\"isGenerated\":false,\"isUpdatedAt\":false},{\"name\":\"value\",\"kind\":\"scalar\",\"isList\":false,\"isRequired\":true,\"isUnique\":false,\"isId\":false,\"isReadOnly\":false,\"hasDefaultValue\":false,\"type\":\"Float\",\"isGenerated\":false,\"isUpdatedAt\":false},{\"name\":\"unit\",\"kind\":\"scalar\",\"isList\":false,\"isRequired\":true,\"isUnique\":false,\"isId\":false,\"isReadOnly\":false,\"hasDefaultValue\":true,\"type\":\"String\",\"default\":\"kWh\",\"isGenerated\":false,\"isUpdatedAt\":false},{\"name\":\"notes\",\"kind\":\"scalar\",\"isList\":false,\"isRequired\":false,\"isUnique\":false,\"isId\":false,\"isReadOnly\":false,\"hasDefaultValue\":false,\"type\":\"String\",\"isGenerated\":false,\"isUpdatedAt\":false},{\"name\":\"createdAt\",\"kind\":\"scalar\",\"isList\":false,\"isRequired\":true,\"isUnique\":false,\"isId\":false,\"isReadOnly\":false,\"hasDefaultValue\":true,\"type\":\"DateTime\",\"default\":{\"name\":\"now\",\"args\":[]},\"isGenerated\":false,\"isUpdatedAt\":false}],\"primaryKey\":null,\"uniqueFields\":[],\"uniqueIndexes\":[],\"isGenerated\":false},\"SalesPlatform\":{\"dbName\":null,\"fields\":[{\"name\":\"id\",\"kind\":\"scalar\",\"isList\":false,\"isRequired\":true,\"isUnique\":false,\"isId\":true,\"isReadOnly\":false,\"hasDefaultValue\":true,\"type\":\"Int\",\"default\":{\"name\":\"autoincrement\",\"args\":[]},\"isGenerated\":false,\"isUpdatedAt\":false},{\"name\":\"name\",\"kind\":\"scalar\",\"isList\":false,\"isRequired\":true,\"isUnique\":true,\"isId\":false,\"isReadOnly\":false,\"hasDefaultValue\":false,\"type\":\"String\",\"isGenerated\":false,\"isUpdatedAt\":false},{\"name\":\"contactInfo\",\"kind\":\"scalar\",\"isList\":false,\"isRequired\":false,\"isUnique\":false,\"isId\":false,\"isReadOnly\":false,\"hasDefaultValue\":false,\"type\":\"String\",\"isGenerated\":false,\"isUpdatedAt\":false},{\"name\":\"isActive\",\"kind\":\"scalar\",\"isList\":false,\"isRequired\":true,\"isUnique\":false,\"isId\":false,\"isReadOnly\":false,\"hasDefaultValue\":true,\"type\":\"Boolean\",\"default\":true,\"isGenerated\":false,\"isUpdatedAt\":false},{\"name\":\"contracts\",\"kind\":\"object\",\"isList\":true,\"isRequired\":true,\"isUnique\":false,\"isId\":false,\"isReadOnly\":false,\"hasDefaultValue\":false,\"type\":\"Contract\",\"relationName\":\"ContractToSalesPlatform\",\"relationFromFields\":[],\"relationToFields\":[],\"isGenerated\":false,\"isUpdatedAt\":false},{\"name\":\"createdAt\",\"kind\":\"scalar\",\"isList\":false,\"isRequired\":true,\"isUnique\":false,\"isId\":false,\"isReadOnly\":false,\"hasDefaultValue\":true,\"type\":\"DateTime\",\"default\":{\"name\":\"now\",\"args\":[]},\"isGenerated\":false,\"isUpdatedAt\":false},{\"name\":\"updatedAt\",\"kind\":\"scalar\",\"isList\":false,\"isRequired\":true,\"isUnique\":false,\"isId\":false,\"isReadOnly\":false,\"hasDefaultValue\":false,\"type\":\"DateTime\",\"isGenerated\":false,\"isUpdatedAt\":true}],\"primaryKey\":null,\"uniqueFields\":[],\"uniqueIndexes\":[],\"isGenerated\":false},\"CancellationPeriod\":{\"dbName\":null,\"fields\":[{\"name\":\"id\",\"kind\":\"scalar\",\"isList\":false,\"isRequired\":true,\"isUnique\":false,\"isId\":true,\"isReadOnly\":false,\"hasDefaultValue\":true,\"type\":\"Int\",\"default\":{\"name\":\"autoincrement\",\"args\":[]},\"isGenerated\":false,\"isUpdatedAt\":false},{\"name\":\"code\",\"kind\":\"scalar\",\"isList\":false,\"isRequired\":true,\"isUnique\":true,\"isId\":false,\"isReadOnly\":false,\"hasDefaultValue\":false,\"type\":\"String\",\"isGenerated\":false,\"isUpdatedAt\":false},{\"name\":\"description\",\"kind\":\"scalar\",\"isList\":false,\"isRequired\":true,\"isUnique\":false,\"isId\":false,\"isReadOnly\":false,\"hasDefaultValue\":false,\"type\":\"String\",\"isGenerated\":false,\"isUpdatedAt\":false},{\"name\":\"isActive\",\"kind\":\"scalar\",\"isList\":false,\"isRequired\":true,\"isUnique\":false,\"isId\":false,\"isReadOnly\":false,\"hasDefaultValue\":true,\"type\":\"Boolean\",\"default\":true,\"isGenerated\":false,\"isUpdatedAt\":false},{\"name\":\"contracts\",\"kind\":\"object\",\"isList\":true,\"isRequired\":true,\"isUnique\":false,\"isId\":false,\"isReadOnly\":false,\"hasDefaultValue\":false,\"type\":\"Contract\",\"relationName\":\"CancellationPeriodToContract\",\"relationFromFields\":[],\"relationToFields\":[],\"isGenerated\":false,\"isUpdatedAt\":false},{\"name\":\"createdAt\",\"kind\":\"scalar\",\"isList\":false,\"isRequired\":true,\"isUnique\":false,\"isId\":false,\"isReadOnly\":false,\"hasDefaultValue\":true,\"type\":\"DateTime\",\"default\":{\"name\":\"now\",\"args\":[]},\"isGenerated\":false,\"isUpdatedAt\":false},{\"name\":\"updatedAt\",\"kind\":\"scalar\",\"isList\":false,\"isRequired\":true,\"isUnique\":false,\"isId\":false,\"isReadOnly\":false,\"hasDefaultValue\":false,\"type\":\"DateTime\",\"isGenerated\":false,\"isUpdatedAt\":true}],\"primaryKey\":null,\"uniqueFields\":[],\"uniqueIndexes\":[],\"isGenerated\":false},\"ContractDuration\":{\"dbName\":null,\"fields\":[{\"name\":\"id\",\"kind\":\"scalar\",\"isList\":false,\"isRequired\":true,\"isUnique\":false,\"isId\":true,\"isReadOnly\":false,\"hasDefaultValue\":true,\"type\":\"Int\",\"default\":{\"name\":\"autoincrement\",\"args\":[]},\"isGenerated\":false,\"isUpdatedAt\":false},{\"name\":\"code\",\"kind\":\"scalar\",\"isList\":false,\"isRequired\":true,\"isUnique\":true,\"isId\":false,\"isReadOnly\":false,\"hasDefaultValue\":false,\"type\":\"String\",\"isGenerated\":false,\"isUpdatedAt\":false},{\"name\":\"description\",\"kind\":\"scalar\",\"isList\":false,\"isRequired\":true,\"isUnique\":false,\"isId\":false,\"isReadOnly\":false,\"hasDefaultValue\":false,\"type\":\"String\",\"isGenerated\":false,\"isUpdatedAt\":false},{\"name\":\"isActive\",\"kind\":\"scalar\",\"isList\":false,\"isRequired\":true,\"isUnique\":false,\"isId\":false,\"isReadOnly\":false,\"hasDefaultValue\":true,\"type\":\"Boolean\",\"default\":true,\"isGenerated\":false,\"isUpdatedAt\":false},{\"name\":\"contracts\",\"kind\":\"object\",\"isList\":true,\"isRequired\":true,\"isUnique\":false,\"isId\":false,\"isReadOnly\":false,\"hasDefaultValue\":false,\"type\":\"Contract\",\"relationName\":\"ContractToContractDuration\",\"relationFromFields\":[],\"relationToFields\":[],\"isGenerated\":false,\"isUpdatedAt\":false},{\"name\":\"createdAt\",\"kind\":\"scalar\",\"isList\":false,\"isRequired\":true,\"isUnique\":false,\"isId\":false,\"isReadOnly\":false,\"hasDefaultValue\":true,\"type\":\"DateTime\",\"default\":{\"name\":\"now\",\"args\":[]},\"isGenerated\":false,\"isUpdatedAt\":false},{\"name\":\"updatedAt\",\"kind\":\"scalar\",\"isList\":false,\"isRequired\":true,\"isUnique\":false,\"isId\":false,\"isReadOnly\":false,\"hasDefaultValue\":false,\"type\":\"DateTime\",\"isGenerated\":false,\"isUpdatedAt\":true}],\"primaryKey\":null,\"uniqueFields\":[],\"uniqueIndexes\":[],\"isGenerated\":false},\"Provider\":{\"dbName\":null,\"fields\":[{\"name\":\"id\",\"kind\":\"scalar\",\"isList\":false,\"isRequired\":true,\"isUnique\":false,\"isId\":true,\"isReadOnly\":false,\"hasDefaultValue\":true,\"type\":\"Int\",\"default\":{\"name\":\"autoincrement\",\"args\":[]},\"isGenerated\":false,\"isUpdatedAt\":false},{\"name\":\"name\",\"kind\":\"scalar\",\"isList\":false,\"isRequired\":true,\"isUnique\":true,\"isId\":false,\"isReadOnly\":false,\"hasDefaultValue\":false,\"type\":\"String\",\"isGenerated\":false,\"isUpdatedAt\":false},{\"name\":\"portalUrl\",\"kind\":\"scalar\",\"isList\":false,\"isRequired\":false,\"isUnique\":false,\"isId\":false,\"isReadOnly\":false,\"hasDefaultValue\":false,\"type\":\"String\",\"isGenerated\":false,\"isUpdatedAt\":false},{\"name\":\"usernameFieldName\",\"kind\":\"scalar\",\"isList\":false,\"isRequired\":false,\"isUnique\":false,\"isId\":false,\"isReadOnly\":false,\"hasDefaultValue\":false,\"type\":\"String\",\"isGenerated\":false,\"isUpdatedAt\":false},{\"name\":\"passwordFieldName\",\"kind\":\"scalar\",\"isList\":false,\"isRequired\":false,\"isUnique\":false,\"isId\":false,\"isReadOnly\":false,\"hasDefaultValue\":false,\"type\":\"String\",\"isGenerated\":false,\"isUpdatedAt\":false},{\"name\":\"isActive\",\"kind\":\"scalar\",\"isList\":false,\"isRequired\":true,\"isUnique\":false,\"isId\":false,\"isReadOnly\":false,\"hasDefaultValue\":true,\"type\":\"Boolean\",\"default\":true,\"isGenerated\":false,\"isUpdatedAt\":false},{\"name\":\"tariffs\",\"kind\":\"object\",\"isList\":true,\"isRequired\":true,\"isUnique\":false,\"isId\":false,\"isReadOnly\":false,\"hasDefaultValue\":false,\"type\":\"Tariff\",\"relationName\":\"ProviderToTariff\",\"relationFromFields\":[],\"relationToFields\":[],\"isGenerated\":false,\"isUpdatedAt\":false},{\"name\":\"contracts\",\"kind\":\"object\",\"isList\":true,\"isRequired\":true,\"isUnique\":false,\"isId\":false,\"isReadOnly\":false,\"hasDefaultValue\":false,\"type\":\"Contract\",\"relationName\":\"ContractToProvider\",\"relationFromFields\":[],\"relationToFields\":[],\"isGenerated\":false,\"isUpdatedAt\":false},{\"name\":\"createdAt\",\"kind\":\"scalar\",\"isList\":false,\"isRequired\":true,\"isUnique\":false,\"isId\":false,\"isReadOnly\":false,\"hasDefaultValue\":true,\"type\":\"DateTime\",\"default\":{\"name\":\"now\",\"args\":[]},\"isGenerated\":false,\"isUpdatedAt\":false},{\"name\":\"updatedAt\",\"kind\":\"scalar\",\"isList\":false,\"isRequired\":true,\"isUnique\":false,\"isId\":false,\"isReadOnly\":false,\"hasDefaultValue\":false,\"type\":\"DateTime\",\"isGenerated\":false,\"isUpdatedAt\":true}],\"primaryKey\":null,\"uniqueFields\":[],\"uniqueIndexes\":[],\"isGenerated\":false},\"Tariff\":{\"dbName\":null,\"fields\":[{\"name\":\"id\",\"kind\":\"scalar\",\"isList\":false,\"isRequired\":true,\"isUnique\":false,\"isId\":true,\"isReadOnly\":false,\"hasDefaultValue\":true,\"type\":\"Int\",\"default\":{\"name\":\"autoincrement\",\"args\":[]},\"isGenerated\":false,\"isUpdatedAt\":false},{\"name\":\"providerId\",\"kind\":\"scalar\",\"isList\":false,\"isRequired\":true,\"isUnique\":false,\"isId\":false,\"isReadOnly\":true,\"hasDefaultValue\":false,\"type\":\"Int\",\"isGenerated\":false,\"isUpdatedAt\":false},{\"name\":\"provider\",\"kind\":\"object\",\"isList\":false,\"isRequired\":true,\"isUnique\":false,\"isId\":false,\"isReadOnly\":false,\"hasDefaultValue\":false,\"type\":\"Provider\",\"relationName\":\"ProviderToTariff\",\"relationFromFields\":[\"providerId\"],\"relationToFields\":[\"id\"],\"relationOnDelete\":\"Cascade\",\"isGenerated\":false,\"isUpdatedAt\":false},{\"name\":\"name\",\"kind\":\"scalar\",\"isList\":false,\"isRequired\":true,\"isUnique\":false,\"isId\":false,\"isReadOnly\":false,\"hasDefaultValue\":false,\"type\":\"String\",\"isGenerated\":false,\"isUpdatedAt\":false},{\"name\":\"isActive\",\"kind\":\"scalar\",\"isList\":false,\"isRequired\":true,\"isUnique\":false,\"isId\":false,\"isReadOnly\":false,\"hasDefaultValue\":true,\"type\":\"Boolean\",\"default\":true,\"isGenerated\":false,\"isUpdatedAt\":false},{\"name\":\"contracts\",\"kind\":\"object\",\"isList\":true,\"isRequired\":true,\"isUnique\":false,\"isId\":false,\"isReadOnly\":false,\"hasDefaultValue\":false,\"type\":\"Contract\",\"relationName\":\"ContractToTariff\",\"relationFromFields\":[],\"relationToFields\":[],\"isGenerated\":false,\"isUpdatedAt\":false},{\"name\":\"createdAt\",\"kind\":\"scalar\",\"isList\":false,\"isRequired\":true,\"isUnique\":false,\"isId\":false,\"isReadOnly\":false,\"hasDefaultValue\":true,\"type\":\"DateTime\",\"default\":{\"name\":\"now\",\"args\":[]},\"isGenerated\":false,\"isUpdatedAt\":false},{\"name\":\"updatedAt\",\"kind\":\"scalar\",\"isList\":false,\"isRequired\":true,\"isUnique\":false,\"isId\":false,\"isReadOnly\":false,\"hasDefaultValue\":false,\"type\":\"DateTime\",\"isGenerated\":false,\"isUpdatedAt\":true}],\"primaryKey\":null,\"uniqueFields\":[[\"providerId\",\"name\"]],\"uniqueIndexes\":[{\"name\":null,\"fields\":[\"providerId\",\"name\"]}],\"isGenerated\":false},\"ContractCategory\":{\"dbName\":null,\"fields\":[{\"name\":\"id\",\"kind\":\"scalar\",\"isList\":false,\"isRequired\":true,\"isUnique\":false,\"isId\":true,\"isReadOnly\":false,\"hasDefaultValue\":true,\"type\":\"Int\",\"default\":{\"name\":\"autoincrement\",\"args\":[]},\"isGenerated\":false,\"isUpdatedAt\":false},{\"name\":\"code\",\"kind\":\"scalar\",\"isList\":false,\"isRequired\":true,\"isUnique\":true,\"isId\":false,\"isReadOnly\":false,\"hasDefaultValue\":false,\"type\":\"String\",\"isGenerated\":false,\"isUpdatedAt\":false},{\"name\":\"name\",\"kind\":\"scalar\",\"isList\":false,\"isRequired\":true,\"isUnique\":false,\"isId\":false,\"isReadOnly\":false,\"hasDefaultValue\":false,\"type\":\"String\",\"isGenerated\":false,\"isUpdatedAt\":false},{\"name\":\"icon\",\"kind\":\"scalar\",\"isList\":false,\"isRequired\":false,\"isUnique\":false,\"isId\":false,\"isReadOnly\":false,\"hasDefaultValue\":false,\"type\":\"String\",\"isGenerated\":false,\"isUpdatedAt\":false},{\"name\":\"color\",\"kind\":\"scalar\",\"isList\":false,\"isRequired\":false,\"isUnique\":false,\"isId\":false,\"isReadOnly\":false,\"hasDefaultValue\":false,\"type\":\"String\",\"isGenerated\":false,\"isUpdatedAt\":false},{\"name\":\"sortOrder\",\"kind\":\"scalar\",\"isList\":false,\"isRequired\":true,\"isUnique\":false,\"isId\":false,\"isReadOnly\":false,\"hasDefaultValue\":true,\"type\":\"Int\",\"default\":0,\"isGenerated\":false,\"isUpdatedAt\":false},{\"name\":\"isActive\",\"kind\":\"scalar\",\"isList\":false,\"isRequired\":true,\"isUnique\":false,\"isId\":false,\"isReadOnly\":false,\"hasDefaultValue\":true,\"type\":\"Boolean\",\"default\":true,\"isGenerated\":false,\"isUpdatedAt\":false},{\"name\":\"contracts\",\"kind\":\"object\",\"isList\":true,\"isRequired\":true,\"isUnique\":false,\"isId\":false,\"isReadOnly\":false,\"hasDefaultValue\":false,\"type\":\"Contract\",\"relationName\":\"ContractToContractCategory\",\"relationFromFields\":[],\"relationToFields\":[],\"isGenerated\":false,\"isUpdatedAt\":false},{\"name\":\"createdAt\",\"kind\":\"scalar\",\"isList\":false,\"isRequired\":true,\"isUnique\":false,\"isId\":false,\"isReadOnly\":false,\"hasDefaultValue\":true,\"type\":\"DateTime\",\"default\":{\"name\":\"now\",\"args\":[]},\"isGenerated\":false,\"isUpdatedAt\":false},{\"name\":\"updatedAt\",\"kind\":\"scalar\",\"isList\":false,\"isRequired\":true,\"isUnique\":false,\"isId\":false,\"isReadOnly\":false,\"hasDefaultValue\":false,\"type\":\"DateTime\",\"isGenerated\":false,\"isUpdatedAt\":true}],\"primaryKey\":null,\"uniqueFields\":[],\"uniqueIndexes\":[],\"isGenerated\":false},\"Contract\":{\"dbName\":null,\"fields\":[{\"name\":\"id\",\"kind\":\"scalar\",\"isList\":false,\"isRequired\":true,\"isUnique\":false,\"isId\":true,\"isReadOnly\":false,\"hasDefaultValue\":true,\"type\":\"Int\",\"default\":{\"name\":\"autoincrement\",\"args\":[]},\"isGenerated\":false,\"isUpdatedAt\":false},{\"name\":\"contractNumber\",\"kind\":\"scalar\",\"isList\":false,\"isRequired\":true,\"isUnique\":true,\"isId\":false,\"isReadOnly\":false,\"hasDefaultValue\":false,\"type\":\"String\",\"isGenerated\":false,\"isUpdatedAt\":false},{\"name\":\"customerId\",\"kind\":\"scalar\",\"isList\":false,\"isRequired\":true,\"isUnique\":false,\"isId\":false,\"isReadOnly\":true,\"hasDefaultValue\":false,\"type\":\"Int\",\"isGenerated\":false,\"isUpdatedAt\":false},{\"name\":\"customer\",\"kind\":\"object\",\"isList\":false,\"isRequired\":true,\"isUnique\":false,\"isId\":false,\"isReadOnly\":false,\"hasDefaultValue\":false,\"type\":\"Customer\",\"relationName\":\"ContractToCustomer\",\"relationFromFields\":[\"customerId\"],\"relationToFields\":[\"id\"],\"relationOnDelete\":\"Cascade\",\"isGenerated\":false,\"isUpdatedAt\":false},{\"name\":\"type\",\"kind\":\"enum\",\"isList\":false,\"isRequired\":true,\"isUnique\":false,\"isId\":false,\"isReadOnly\":false,\"hasDefaultValue\":false,\"type\":\"ContractType\",\"isGenerated\":false,\"isUpdatedAt\":false},{\"name\":\"status\",\"kind\":\"enum\",\"isList\":false,\"isRequired\":true,\"isUnique\":false,\"isId\":false,\"isReadOnly\":false,\"hasDefaultValue\":true,\"type\":\"ContractStatus\",\"default\":\"DRAFT\",\"isGenerated\":false,\"isUpdatedAt\":false},{\"name\":\"contractCategoryId\",\"kind\":\"scalar\",\"isList\":false,\"isRequired\":false,\"isUnique\":false,\"isId\":false,\"isReadOnly\":true,\"hasDefaultValue\":false,\"type\":\"Int\",\"isGenerated\":false,\"isUpdatedAt\":false},{\"name\":\"contractCategory\",\"kind\":\"object\",\"isList\":false,\"isRequired\":false,\"isUnique\":false,\"isId\":false,\"isReadOnly\":false,\"hasDefaultValue\":false,\"type\":\"ContractCategory\",\"relationName\":\"ContractToContractCategory\",\"relationFromFields\":[\"contractCategoryId\"],\"relationToFields\":[\"id\"],\"isGenerated\":false,\"isUpdatedAt\":false},{\"name\":\"addressId\",\"kind\":\"scalar\",\"isList\":false,\"isRequired\":false,\"isUnique\":false,\"isId\":false,\"isReadOnly\":true,\"hasDefaultValue\":false,\"type\":\"Int\",\"isGenerated\":false,\"isUpdatedAt\":false},{\"name\":\"address\",\"kind\":\"object\",\"isList\":false,\"isRequired\":false,\"isUnique\":false,\"isId\":false,\"isReadOnly\":false,\"hasDefaultValue\":false,\"type\":\"Address\",\"relationName\":\"AddressToContract\",\"relationFromFields\":[\"addressId\"],\"relationToFields\":[\"id\"],\"isGenerated\":false,\"isUpdatedAt\":false},{\"name\":\"bankCardId\",\"kind\":\"scalar\",\"isList\":false,\"isRequired\":false,\"isUnique\":false,\"isId\":false,\"isReadOnly\":true,\"hasDefaultValue\":false,\"type\":\"Int\",\"isGenerated\":false,\"isUpdatedAt\":false},{\"name\":\"bankCard\",\"kind\":\"object\",\"isList\":false,\"isRequired\":false,\"isUnique\":false,\"isId\":false,\"isReadOnly\":false,\"hasDefaultValue\":false,\"type\":\"BankCard\",\"relationName\":\"BankCardToContract\",\"relationFromFields\":[\"bankCardId\"],\"relationToFields\":[\"id\"],\"isGenerated\":false,\"isUpdatedAt\":false},{\"name\":\"identityDocumentId\",\"kind\":\"scalar\",\"isList\":false,\"isRequired\":false,\"isUnique\":false,\"isId\":false,\"isReadOnly\":true,\"hasDefaultValue\":false,\"type\":\"Int\",\"isGenerated\":false,\"isUpdatedAt\":false},{\"name\":\"identityDocument\",\"kind\":\"object\",\"isList\":false,\"isRequired\":false,\"isUnique\":false,\"isId\":false,\"isReadOnly\":false,\"hasDefaultValue\":false,\"type\":\"IdentityDocument\",\"relationName\":\"ContractToIdentityDocument\",\"relationFromFields\":[\"identityDocumentId\"],\"relationToFields\":[\"id\"],\"isGenerated\":false,\"isUpdatedAt\":false},{\"name\":\"salesPlatformId\",\"kind\":\"scalar\",\"isList\":false,\"isRequired\":false,\"isUnique\":false,\"isId\":false,\"isReadOnly\":true,\"hasDefaultValue\":false,\"type\":\"Int\",\"isGenerated\":false,\"isUpdatedAt\":false},{\"name\":\"salesPlatform\",\"kind\":\"object\",\"isList\":false,\"isRequired\":false,\"isUnique\":false,\"isId\":false,\"isReadOnly\":false,\"hasDefaultValue\":false,\"type\":\"SalesPlatform\",\"relationName\":\"ContractToSalesPlatform\",\"relationFromFields\":[\"salesPlatformId\"],\"relationToFields\":[\"id\"],\"isGenerated\":false,\"isUpdatedAt\":false},{\"name\":\"cancellationPeriodId\",\"kind\":\"scalar\",\"isList\":false,\"isRequired\":false,\"isUnique\":false,\"isId\":false,\"isReadOnly\":true,\"hasDefaultValue\":false,\"type\":\"Int\",\"isGenerated\":false,\"isUpdatedAt\":false},{\"name\":\"cancellationPeriod\",\"kind\":\"object\",\"isList\":false,\"isRequired\":false,\"isUnique\":false,\"isId\":false,\"isReadOnly\":false,\"hasDefaultValue\":false,\"type\":\"CancellationPeriod\",\"relationName\":\"CancellationPeriodToContract\",\"relationFromFields\":[\"cancellationPeriodId\"],\"relationToFields\":[\"id\"],\"isGenerated\":false,\"isUpdatedAt\":false},{\"name\":\"contractDurationId\",\"kind\":\"scalar\",\"isList\":false,\"isRequired\":false,\"isUnique\":false,\"isId\":false,\"isReadOnly\":true,\"hasDefaultValue\":false,\"type\":\"Int\",\"isGenerated\":false,\"isUpdatedAt\":false},{\"name\":\"contractDuration\",\"kind\":\"object\",\"isList\":false,\"isRequired\":false,\"isUnique\":false,\"isId\":false,\"isReadOnly\":false,\"hasDefaultValue\":false,\"type\":\"ContractDuration\",\"relationName\":\"ContractToContractDuration\",\"relationFromFields\":[\"contractDurationId\"],\"relationToFields\":[\"id\"],\"isGenerated\":false,\"isUpdatedAt\":false},{\"name\":\"previousContractId\",\"kind\":\"scalar\",\"isList\":false,\"isRequired\":false,\"isUnique\":true,\"isId\":false,\"isReadOnly\":true,\"hasDefaultValue\":false,\"type\":\"Int\",\"isGenerated\":false,\"isUpdatedAt\":false},{\"name\":\"previousContract\",\"kind\":\"object\",\"isList\":false,\"isRequired\":false,\"isUnique\":false,\"isId\":false,\"isReadOnly\":false,\"hasDefaultValue\":false,\"type\":\"Contract\",\"relationName\":\"ContractHistory\",\"relationFromFields\":[\"previousContractId\"],\"relationToFields\":[\"id\"],\"isGenerated\":false,\"isUpdatedAt\":false},{\"name\":\"followUpContract\",\"kind\":\"object\",\"isList\":false,\"isRequired\":false,\"isUnique\":false,\"isId\":false,\"isReadOnly\":false,\"hasDefaultValue\":false,\"type\":\"Contract\",\"relationName\":\"ContractHistory\",\"relationFromFields\":[],\"relationToFields\":[],\"isGenerated\":false,\"isUpdatedAt\":false},{\"name\":\"providerId\",\"kind\":\"scalar\",\"isList\":false,\"isRequired\":false,\"isUnique\":false,\"isId\":false,\"isReadOnly\":true,\"hasDefaultValue\":false,\"type\":\"Int\",\"isGenerated\":false,\"isUpdatedAt\":false},{\"name\":\"provider\",\"kind\":\"object\",\"isList\":false,\"isRequired\":false,\"isUnique\":false,\"isId\":false,\"isReadOnly\":false,\"hasDefaultValue\":false,\"type\":\"Provider\",\"relationName\":\"ContractToProvider\",\"relationFromFields\":[\"providerId\"],\"relationToFields\":[\"id\"],\"isGenerated\":false,\"isUpdatedAt\":false},{\"name\":\"tariffId\",\"kind\":\"scalar\",\"isList\":false,\"isRequired\":false,\"isUnique\":false,\"isId\":false,\"isReadOnly\":true,\"hasDefaultValue\":false,\"type\":\"Int\",\"isGenerated\":false,\"isUpdatedAt\":false},{\"name\":\"tariff\",\"kind\":\"object\",\"isList\":false,\"isRequired\":false,\"isUnique\":false,\"isId\":false,\"isReadOnly\":false,\"hasDefaultValue\":false,\"type\":\"Tariff\",\"relationName\":\"ContractToTariff\",\"relationFromFields\":[\"tariffId\"],\"relationToFields\":[\"id\"],\"isGenerated\":false,\"isUpdatedAt\":false},{\"name\":\"providerName\",\"kind\":\"scalar\",\"isList\":false,\"isRequired\":false,\"isUnique\":false,\"isId\":false,\"isReadOnly\":false,\"hasDefaultValue\":false,\"type\":\"String\",\"isGenerated\":false,\"isUpdatedAt\":false},{\"name\":\"tariffName\",\"kind\":\"scalar\",\"isList\":false,\"isRequired\":false,\"isUnique\":false,\"isId\":false,\"isReadOnly\":false,\"hasDefaultValue\":false,\"type\":\"String\",\"isGenerated\":false,\"isUpdatedAt\":false},{\"name\":\"customerNumberAtProvider\",\"kind\":\"scalar\",\"isList\":false,\"isRequired\":false,\"isUnique\":false,\"isId\":false,\"isReadOnly\":false,\"hasDefaultValue\":false,\"type\":\"String\",\"isGenerated\":false,\"isUpdatedAt\":false},{\"name\":\"priceFirst12Months\",\"kind\":\"scalar\",\"isList\":false,\"isRequired\":false,\"isUnique\":false,\"isId\":false,\"isReadOnly\":false,\"hasDefaultValue\":false,\"type\":\"String\",\"isGenerated\":false,\"isUpdatedAt\":false},{\"name\":\"priceFrom13Months\",\"kind\":\"scalar\",\"isList\":false,\"isRequired\":false,\"isUnique\":false,\"isId\":false,\"isReadOnly\":false,\"hasDefaultValue\":false,\"type\":\"String\",\"isGenerated\":false,\"isUpdatedAt\":false},{\"name\":\"priceAfter24Months\",\"kind\":\"scalar\",\"isList\":false,\"isRequired\":false,\"isUnique\":false,\"isId\":false,\"isReadOnly\":false,\"hasDefaultValue\":false,\"type\":\"String\",\"isGenerated\":false,\"isUpdatedAt\":false},{\"name\":\"startDate\",\"kind\":\"scalar\",\"isList\":false,\"isRequired\":false,\"isUnique\":false,\"isId\":false,\"isReadOnly\":false,\"hasDefaultValue\":false,\"type\":\"DateTime\",\"isGenerated\":false,\"isUpdatedAt\":false},{\"name\":\"endDate\",\"kind\":\"scalar\",\"isList\":false,\"isRequired\":false,\"isUnique\":false,\"isId\":false,\"isReadOnly\":false,\"hasDefaultValue\":false,\"type\":\"DateTime\",\"isGenerated\":false,\"isUpdatedAt\":false},{\"name\":\"commission\",\"kind\":\"scalar\",\"isList\":false,\"isRequired\":false,\"isUnique\":false,\"isId\":false,\"isReadOnly\":false,\"hasDefaultValue\":false,\"type\":\"Float\",\"isGenerated\":false,\"isUpdatedAt\":false},{\"name\":\"cancellationLetterPath\",\"kind\":\"scalar\",\"isList\":false,\"isRequired\":false,\"isUnique\":false,\"isId\":false,\"isReadOnly\":false,\"hasDefaultValue\":false,\"type\":\"String\",\"isGenerated\":false,\"isUpdatedAt\":false},{\"name\":\"cancellationConfirmationPath\",\"kind\":\"scalar\",\"isList\":false,\"isRequired\":false,\"isUnique\":false,\"isId\":false,\"isReadOnly\":false,\"hasDefaultValue\":false,\"type\":\"String\",\"isGenerated\":false,\"isUpdatedAt\":false},{\"name\":\"cancellationLetterOptionsPath\",\"kind\":\"scalar\",\"isList\":false,\"isRequired\":false,\"isUnique\":false,\"isId\":false,\"isReadOnly\":false,\"hasDefaultValue\":false,\"type\":\"String\",\"isGenerated\":false,\"isUpdatedAt\":false},{\"name\":\"cancellationConfirmationOptionsPath\",\"kind\":\"scalar\",\"isList\":false,\"isRequired\":false,\"isUnique\":false,\"isId\":false,\"isReadOnly\":false,\"hasDefaultValue\":false,\"type\":\"String\",\"isGenerated\":false,\"isUpdatedAt\":false},{\"name\":\"cancellationConfirmationDate\",\"kind\":\"scalar\",\"isList\":false,\"isRequired\":false,\"isUnique\":false,\"isId\":false,\"isReadOnly\":false,\"hasDefaultValue\":false,\"type\":\"DateTime\",\"isGenerated\":false,\"isUpdatedAt\":false},{\"name\":\"cancellationConfirmationOptionsDate\",\"kind\":\"scalar\",\"isList\":false,\"isRequired\":false,\"isUnique\":false,\"isId\":false,\"isReadOnly\":false,\"hasDefaultValue\":false,\"type\":\"DateTime\",\"isGenerated\":false,\"isUpdatedAt\":false},{\"name\":\"wasSpecialCancellation\",\"kind\":\"scalar\",\"isList\":false,\"isRequired\":true,\"isUnique\":false,\"isId\":false,\"isReadOnly\":false,\"hasDefaultValue\":true,\"type\":\"Boolean\",\"default\":false,\"isGenerated\":false,\"isUpdatedAt\":false},{\"name\":\"portalUsername\",\"kind\":\"scalar\",\"isList\":false,\"isRequired\":false,\"isUnique\":false,\"isId\":false,\"isReadOnly\":false,\"hasDefaultValue\":false,\"type\":\"String\",\"isGenerated\":false,\"isUpdatedAt\":false},{\"name\":\"portalPasswordEncrypted\",\"kind\":\"scalar\",\"isList\":false,\"isRequired\":false,\"isUnique\":false,\"isId\":false,\"isReadOnly\":false,\"hasDefaultValue\":false,\"type\":\"String\",\"isGenerated\":false,\"isUpdatedAt\":false},{\"name\":\"stressfreiEmailId\",\"kind\":\"scalar\",\"isList\":false,\"isRequired\":false,\"isUnique\":false,\"isId\":false,\"isReadOnly\":true,\"hasDefaultValue\":false,\"type\":\"Int\",\"isGenerated\":false,\"isUpdatedAt\":false},{\"name\":\"stressfreiEmail\",\"kind\":\"object\",\"isList\":false,\"isRequired\":false,\"isUnique\":false,\"isId\":false,\"isReadOnly\":false,\"hasDefaultValue\":false,\"type\":\"StressfreiEmail\",\"relationName\":\"ContractToStressfreiEmail\",\"relationFromFields\":[\"stressfreiEmailId\"],\"relationToFields\":[\"id\"],\"isGenerated\":false,\"isUpdatedAt\":false},{\"name\":\"notes\",\"kind\":\"scalar\",\"isList\":false,\"isRequired\":false,\"isUnique\":false,\"isId\":false,\"isReadOnly\":false,\"hasDefaultValue\":false,\"type\":\"String\",\"isGenerated\":false,\"isUpdatedAt\":false},{\"name\":\"energyDetails\",\"kind\":\"object\",\"isList\":false,\"isRequired\":false,\"isUnique\":false,\"isId\":false,\"isReadOnly\":false,\"hasDefaultValue\":false,\"type\":\"EnergyContractDetails\",\"relationName\":\"ContractToEnergyContractDetails\",\"relationFromFields\":[],\"relationToFields\":[],\"isGenerated\":false,\"isUpdatedAt\":false},{\"name\":\"internetDetails\",\"kind\":\"object\",\"isList\":false,\"isRequired\":false,\"isUnique\":false,\"isId\":false,\"isReadOnly\":false,\"hasDefaultValue\":false,\"type\":\"InternetContractDetails\",\"relationName\":\"ContractToInternetContractDetails\",\"relationFromFields\":[],\"relationToFields\":[],\"isGenerated\":false,\"isUpdatedAt\":false},{\"name\":\"mobileDetails\",\"kind\":\"object\",\"isList\":false,\"isRequired\":false,\"isUnique\":false,\"isId\":false,\"isReadOnly\":false,\"hasDefaultValue\":false,\"type\":\"MobileContractDetails\",\"relationName\":\"ContractToMobileContractDetails\",\"relationFromFields\":[],\"relationToFields\":[],\"isGenerated\":false,\"isUpdatedAt\":false},{\"name\":\"tvDetails\",\"kind\":\"object\",\"isList\":false,\"isRequired\":false,\"isUnique\":false,\"isId\":false,\"isReadOnly\":false,\"hasDefaultValue\":false,\"type\":\"TvContractDetails\",\"relationName\":\"ContractToTvContractDetails\",\"relationFromFields\":[],\"relationToFields\":[],\"isGenerated\":false,\"isUpdatedAt\":false},{\"name\":\"carInsuranceDetails\",\"kind\":\"object\",\"isList\":false,\"isRequired\":false,\"isUnique\":false,\"isId\":false,\"isReadOnly\":false,\"hasDefaultValue\":false,\"type\":\"CarInsuranceDetails\",\"relationName\":\"CarInsuranceDetailsToContract\",\"relationFromFields\":[],\"relationToFields\":[],\"isGenerated\":false,\"isUpdatedAt\":false},{\"name\":\"tasks\",\"kind\":\"object\",\"isList\":true,\"isRequired\":true,\"isUnique\":false,\"isId\":false,\"isReadOnly\":false,\"hasDefaultValue\":false,\"type\":\"ContractTask\",\"relationName\":\"ContractToContractTask\",\"relationFromFields\":[],\"relationToFields\":[],\"isGenerated\":false,\"isUpdatedAt\":false},{\"name\":\"createdAt\",\"kind\":\"scalar\",\"isList\":false,\"isRequired\":true,\"isUnique\":false,\"isId\":false,\"isReadOnly\":false,\"hasDefaultValue\":true,\"type\":\"DateTime\",\"default\":{\"name\":\"now\",\"args\":[]},\"isGenerated\":false,\"isUpdatedAt\":false},{\"name\":\"updatedAt\",\"kind\":\"scalar\",\"isList\":false,\"isRequired\":true,\"isUnique\":false,\"isId\":false,\"isReadOnly\":false,\"hasDefaultValue\":false,\"type\":\"DateTime\",\"isGenerated\":false,\"isUpdatedAt\":true}],\"primaryKey\":null,\"uniqueFields\":[],\"uniqueIndexes\":[],\"isGenerated\":false},\"ContractTask\":{\"dbName\":null,\"fields\":[{\"name\":\"id\",\"kind\":\"scalar\",\"isList\":false,\"isRequired\":true,\"isUnique\":false,\"isId\":true,\"isReadOnly\":false,\"hasDefaultValue\":true,\"type\":\"Int\",\"default\":{\"name\":\"autoincrement\",\"args\":[]},\"isGenerated\":false,\"isUpdatedAt\":false},{\"name\":\"contractId\",\"kind\":\"scalar\",\"isList\":false,\"isRequired\":true,\"isUnique\":false,\"isId\":false,\"isReadOnly\":true,\"hasDefaultValue\":false,\"type\":\"Int\",\"isGenerated\":false,\"isUpdatedAt\":false},{\"name\":\"contract\",\"kind\":\"object\",\"isList\":false,\"isRequired\":true,\"isUnique\":false,\"isId\":false,\"isReadOnly\":false,\"hasDefaultValue\":false,\"type\":\"Contract\",\"relationName\":\"ContractToContractTask\",\"relationFromFields\":[\"contractId\"],\"relationToFields\":[\"id\"],\"relationOnDelete\":\"Cascade\",\"isGenerated\":false,\"isUpdatedAt\":false},{\"name\":\"title\",\"kind\":\"scalar\",\"isList\":false,\"isRequired\":true,\"isUnique\":false,\"isId\":false,\"isReadOnly\":false,\"hasDefaultValue\":false,\"type\":\"String\",\"isGenerated\":false,\"isUpdatedAt\":false},{\"name\":\"description\",\"kind\":\"scalar\",\"isList\":false,\"isRequired\":false,\"isUnique\":false,\"isId\":false,\"isReadOnly\":false,\"hasDefaultValue\":false,\"type\":\"String\",\"isGenerated\":false,\"isUpdatedAt\":false},{\"name\":\"status\",\"kind\":\"enum\",\"isList\":false,\"isRequired\":true,\"isUnique\":false,\"isId\":false,\"isReadOnly\":false,\"hasDefaultValue\":true,\"type\":\"ContractTaskStatus\",\"default\":\"OPEN\",\"isGenerated\":false,\"isUpdatedAt\":false},{\"name\":\"visibleInPortal\",\"kind\":\"scalar\",\"isList\":false,\"isRequired\":true,\"isUnique\":false,\"isId\":false,\"isReadOnly\":false,\"hasDefaultValue\":true,\"type\":\"Boolean\",\"default\":false,\"isGenerated\":false,\"isUpdatedAt\":false},{\"name\":\"createdBy\",\"kind\":\"scalar\",\"isList\":false,\"isRequired\":false,\"isUnique\":false,\"isId\":false,\"isReadOnly\":false,\"hasDefaultValue\":false,\"type\":\"String\",\"isGenerated\":false,\"isUpdatedAt\":false},{\"name\":\"completedAt\",\"kind\":\"scalar\",\"isList\":false,\"isRequired\":false,\"isUnique\":false,\"isId\":false,\"isReadOnly\":false,\"hasDefaultValue\":false,\"type\":\"DateTime\",\"isGenerated\":false,\"isUpdatedAt\":false},{\"name\":\"subtasks\",\"kind\":\"object\",\"isList\":true,\"isRequired\":true,\"isUnique\":false,\"isId\":false,\"isReadOnly\":false,\"hasDefaultValue\":false,\"type\":\"ContractTaskSubtask\",\"relationName\":\"ContractTaskToContractTaskSubtask\",\"relationFromFields\":[],\"relationToFields\":[],\"isGenerated\":false,\"isUpdatedAt\":false},{\"name\":\"createdAt\",\"kind\":\"scalar\",\"isList\":false,\"isRequired\":true,\"isUnique\":false,\"isId\":false,\"isReadOnly\":false,\"hasDefaultValue\":true,\"type\":\"DateTime\",\"default\":{\"name\":\"now\",\"args\":[]},\"isGenerated\":false,\"isUpdatedAt\":false},{\"name\":\"updatedAt\",\"kind\":\"scalar\",\"isList\":false,\"isRequired\":true,\"isUnique\":false,\"isId\":false,\"isReadOnly\":false,\"hasDefaultValue\":false,\"type\":\"DateTime\",\"isGenerated\":false,\"isUpdatedAt\":true}],\"primaryKey\":null,\"uniqueFields\":[],\"uniqueIndexes\":[],\"isGenerated\":false},\"ContractTaskSubtask\":{\"dbName\":null,\"fields\":[{\"name\":\"id\",\"kind\":\"scalar\",\"isList\":false,\"isRequired\":true,\"isUnique\":false,\"isId\":true,\"isReadOnly\":false,\"hasDefaultValue\":true,\"type\":\"Int\",\"default\":{\"name\":\"autoincrement\",\"args\":[]},\"isGenerated\":false,\"isUpdatedAt\":false},{\"name\":\"taskId\",\"kind\":\"scalar\",\"isList\":false,\"isRequired\":true,\"isUnique\":false,\"isId\":false,\"isReadOnly\":true,\"hasDefaultValue\":false,\"type\":\"Int\",\"isGenerated\":false,\"isUpdatedAt\":false},{\"name\":\"task\",\"kind\":\"object\",\"isList\":false,\"isRequired\":true,\"isUnique\":false,\"isId\":false,\"isReadOnly\":false,\"hasDefaultValue\":false,\"type\":\"ContractTask\",\"relationName\":\"ContractTaskToContractTaskSubtask\",\"relationFromFields\":[\"taskId\"],\"relationToFields\":[\"id\"],\"relationOnDelete\":\"Cascade\",\"isGenerated\":false,\"isUpdatedAt\":false},{\"name\":\"title\",\"kind\":\"scalar\",\"isList\":false,\"isRequired\":true,\"isUnique\":false,\"isId\":false,\"isReadOnly\":false,\"hasDefaultValue\":false,\"type\":\"String\",\"isGenerated\":false,\"isUpdatedAt\":false},{\"name\":\"status\",\"kind\":\"enum\",\"isList\":false,\"isRequired\":true,\"isUnique\":false,\"isId\":false,\"isReadOnly\":false,\"hasDefaultValue\":true,\"type\":\"ContractTaskStatus\",\"default\":\"OPEN\",\"isGenerated\":false,\"isUpdatedAt\":false},{\"name\":\"createdBy\",\"kind\":\"scalar\",\"isList\":false,\"isRequired\":false,\"isUnique\":false,\"isId\":false,\"isReadOnly\":false,\"hasDefaultValue\":false,\"type\":\"String\",\"isGenerated\":false,\"isUpdatedAt\":false},{\"name\":\"completedAt\",\"kind\":\"scalar\",\"isList\":false,\"isRequired\":false,\"isUnique\":false,\"isId\":false,\"isReadOnly\":false,\"hasDefaultValue\":false,\"type\":\"DateTime\",\"isGenerated\":false,\"isUpdatedAt\":false},{\"name\":\"createdAt\",\"kind\":\"scalar\",\"isList\":false,\"isRequired\":true,\"isUnique\":false,\"isId\":false,\"isReadOnly\":false,\"hasDefaultValue\":true,\"type\":\"DateTime\",\"default\":{\"name\":\"now\",\"args\":[]},\"isGenerated\":false,\"isUpdatedAt\":false},{\"name\":\"updatedAt\",\"kind\":\"scalar\",\"isList\":false,\"isRequired\":true,\"isUnique\":false,\"isId\":false,\"isReadOnly\":false,\"hasDefaultValue\":false,\"type\":\"DateTime\",\"isGenerated\":false,\"isUpdatedAt\":true}],\"primaryKey\":null,\"uniqueFields\":[],\"uniqueIndexes\":[],\"isGenerated\":false},\"EnergyContractDetails\":{\"dbName\":null,\"fields\":[{\"name\":\"id\",\"kind\":\"scalar\",\"isList\":false,\"isRequired\":true,\"isUnique\":false,\"isId\":true,\"isReadOnly\":false,\"hasDefaultValue\":true,\"type\":\"Int\",\"default\":{\"name\":\"autoincrement\",\"args\":[]},\"isGenerated\":false,\"isUpdatedAt\":false},{\"name\":\"contractId\",\"kind\":\"scalar\",\"isList\":false,\"isRequired\":true,\"isUnique\":true,\"isId\":false,\"isReadOnly\":true,\"hasDefaultValue\":false,\"type\":\"Int\",\"isGenerated\":false,\"isUpdatedAt\":false},{\"name\":\"contract\",\"kind\":\"object\",\"isList\":false,\"isRequired\":true,\"isUnique\":false,\"isId\":false,\"isReadOnly\":false,\"hasDefaultValue\":false,\"type\":\"Contract\",\"relationName\":\"ContractToEnergyContractDetails\",\"relationFromFields\":[\"contractId\"],\"relationToFields\":[\"id\"],\"relationOnDelete\":\"Cascade\",\"isGenerated\":false,\"isUpdatedAt\":false},{\"name\":\"meterId\",\"kind\":\"scalar\",\"isList\":false,\"isRequired\":false,\"isUnique\":false,\"isId\":false,\"isReadOnly\":true,\"hasDefaultValue\":false,\"type\":\"Int\",\"isGenerated\":false,\"isUpdatedAt\":false},{\"name\":\"meter\",\"kind\":\"object\",\"isList\":false,\"isRequired\":false,\"isUnique\":false,\"isId\":false,\"isReadOnly\":false,\"hasDefaultValue\":false,\"type\":\"Meter\",\"relationName\":\"EnergyContractDetailsToMeter\",\"relationFromFields\":[\"meterId\"],\"relationToFields\":[\"id\"],\"isGenerated\":false,\"isUpdatedAt\":false},{\"name\":\"annualConsumption\",\"kind\":\"scalar\",\"isList\":false,\"isRequired\":false,\"isUnique\":false,\"isId\":false,\"isReadOnly\":false,\"hasDefaultValue\":false,\"type\":\"Float\",\"isGenerated\":false,\"isUpdatedAt\":false},{\"name\":\"basePrice\",\"kind\":\"scalar\",\"isList\":false,\"isRequired\":false,\"isUnique\":false,\"isId\":false,\"isReadOnly\":false,\"hasDefaultValue\":false,\"type\":\"Float\",\"isGenerated\":false,\"isUpdatedAt\":false},{\"name\":\"unitPrice\",\"kind\":\"scalar\",\"isList\":false,\"isRequired\":false,\"isUnique\":false,\"isId\":false,\"isReadOnly\":false,\"hasDefaultValue\":false,\"type\":\"Float\",\"isGenerated\":false,\"isUpdatedAt\":false},{\"name\":\"bonus\",\"kind\":\"scalar\",\"isList\":false,\"isRequired\":false,\"isUnique\":false,\"isId\":false,\"isReadOnly\":false,\"hasDefaultValue\":false,\"type\":\"Float\",\"isGenerated\":false,\"isUpdatedAt\":false},{\"name\":\"previousProviderName\",\"kind\":\"scalar\",\"isList\":false,\"isRequired\":false,\"isUnique\":false,\"isId\":false,\"isReadOnly\":false,\"hasDefaultValue\":false,\"type\":\"String\",\"isGenerated\":false,\"isUpdatedAt\":false},{\"name\":\"previousCustomerNumber\",\"kind\":\"scalar\",\"isList\":false,\"isRequired\":false,\"isUnique\":false,\"isId\":false,\"isReadOnly\":false,\"hasDefaultValue\":false,\"type\":\"String\",\"isGenerated\":false,\"isUpdatedAt\":false}],\"primaryKey\":null,\"uniqueFields\":[],\"uniqueIndexes\":[],\"isGenerated\":false},\"InternetContractDetails\":{\"dbName\":null,\"fields\":[{\"name\":\"id\",\"kind\":\"scalar\",\"isList\":false,\"isRequired\":true,\"isUnique\":false,\"isId\":true,\"isReadOnly\":false,\"hasDefaultValue\":true,\"type\":\"Int\",\"default\":{\"name\":\"autoincrement\",\"args\":[]},\"isGenerated\":false,\"isUpdatedAt\":false},{\"name\":\"contractId\",\"kind\":\"scalar\",\"isList\":false,\"isRequired\":true,\"isUnique\":true,\"isId\":false,\"isReadOnly\":true,\"hasDefaultValue\":false,\"type\":\"Int\",\"isGenerated\":false,\"isUpdatedAt\":false},{\"name\":\"contract\",\"kind\":\"object\",\"isList\":false,\"isRequired\":true,\"isUnique\":false,\"isId\":false,\"isReadOnly\":false,\"hasDefaultValue\":false,\"type\":\"Contract\",\"relationName\":\"ContractToInternetContractDetails\",\"relationFromFields\":[\"contractId\"],\"relationToFields\":[\"id\"],\"relationOnDelete\":\"Cascade\",\"isGenerated\":false,\"isUpdatedAt\":false},{\"name\":\"downloadSpeed\",\"kind\":\"scalar\",\"isList\":false,\"isRequired\":false,\"isUnique\":false,\"isId\":false,\"isReadOnly\":false,\"hasDefaultValue\":false,\"type\":\"Int\",\"isGenerated\":false,\"isUpdatedAt\":false},{\"name\":\"uploadSpeed\",\"kind\":\"scalar\",\"isList\":false,\"isRequired\":false,\"isUnique\":false,\"isId\":false,\"isReadOnly\":false,\"hasDefaultValue\":false,\"type\":\"Int\",\"isGenerated\":false,\"isUpdatedAt\":false},{\"name\":\"routerModel\",\"kind\":\"scalar\",\"isList\":false,\"isRequired\":false,\"isUnique\":false,\"isId\":false,\"isReadOnly\":false,\"hasDefaultValue\":false,\"type\":\"String\",\"isGenerated\":false,\"isUpdatedAt\":false},{\"name\":\"routerSerialNumber\",\"kind\":\"scalar\",\"isList\":false,\"isRequired\":false,\"isUnique\":false,\"isId\":false,\"isReadOnly\":false,\"hasDefaultValue\":false,\"type\":\"String\",\"isGenerated\":false,\"isUpdatedAt\":false},{\"name\":\"installationDate\",\"kind\":\"scalar\",\"isList\":false,\"isRequired\":false,\"isUnique\":false,\"isId\":false,\"isReadOnly\":false,\"hasDefaultValue\":false,\"type\":\"DateTime\",\"isGenerated\":false,\"isUpdatedAt\":false},{\"name\":\"internetUsername\",\"kind\":\"scalar\",\"isList\":false,\"isRequired\":false,\"isUnique\":false,\"isId\":false,\"isReadOnly\":false,\"hasDefaultValue\":false,\"type\":\"String\",\"isGenerated\":false,\"isUpdatedAt\":false},{\"name\":\"internetPasswordEncrypted\",\"kind\":\"scalar\",\"isList\":false,\"isRequired\":false,\"isUnique\":false,\"isId\":false,\"isReadOnly\":false,\"hasDefaultValue\":false,\"type\":\"String\",\"isGenerated\":false,\"isUpdatedAt\":false},{\"name\":\"homeId\",\"kind\":\"scalar\",\"isList\":false,\"isRequired\":false,\"isUnique\":false,\"isId\":false,\"isReadOnly\":false,\"hasDefaultValue\":false,\"type\":\"String\",\"isGenerated\":false,\"isUpdatedAt\":false},{\"name\":\"activationCode\",\"kind\":\"scalar\",\"isList\":false,\"isRequired\":false,\"isUnique\":false,\"isId\":false,\"isReadOnly\":false,\"hasDefaultValue\":false,\"type\":\"String\",\"isGenerated\":false,\"isUpdatedAt\":false},{\"name\":\"phoneNumbers\",\"kind\":\"object\",\"isList\":true,\"isRequired\":true,\"isUnique\":false,\"isId\":false,\"isReadOnly\":false,\"hasDefaultValue\":false,\"type\":\"PhoneNumber\",\"relationName\":\"InternetContractDetailsToPhoneNumber\",\"relationFromFields\":[],\"relationToFields\":[],\"isGenerated\":false,\"isUpdatedAt\":false}],\"primaryKey\":null,\"uniqueFields\":[],\"uniqueIndexes\":[],\"isGenerated\":false},\"PhoneNumber\":{\"dbName\":null,\"fields\":[{\"name\":\"id\",\"kind\":\"scalar\",\"isList\":false,\"isRequired\":true,\"isUnique\":false,\"isId\":true,\"isReadOnly\":false,\"hasDefaultValue\":true,\"type\":\"Int\",\"default\":{\"name\":\"autoincrement\",\"args\":[]},\"isGenerated\":false,\"isUpdatedAt\":false},{\"name\":\"internetContractDetailsId\",\"kind\":\"scalar\",\"isList\":false,\"isRequired\":true,\"isUnique\":false,\"isId\":false,\"isReadOnly\":true,\"hasDefaultValue\":false,\"type\":\"Int\",\"isGenerated\":false,\"isUpdatedAt\":false},{\"name\":\"internetDetails\",\"kind\":\"object\",\"isList\":false,\"isRequired\":true,\"isUnique\":false,\"isId\":false,\"isReadOnly\":false,\"hasDefaultValue\":false,\"type\":\"InternetContractDetails\",\"relationName\":\"InternetContractDetailsToPhoneNumber\",\"relationFromFields\":[\"internetContractDetailsId\"],\"relationToFields\":[\"id\"],\"relationOnDelete\":\"Cascade\",\"isGenerated\":false,\"isUpdatedAt\":false},{\"name\":\"phoneNumber\",\"kind\":\"scalar\",\"isList\":false,\"isRequired\":true,\"isUnique\":false,\"isId\":false,\"isReadOnly\":false,\"hasDefaultValue\":false,\"type\":\"String\",\"isGenerated\":false,\"isUpdatedAt\":false},{\"name\":\"isMain\",\"kind\":\"scalar\",\"isList\":false,\"isRequired\":true,\"isUnique\":false,\"isId\":false,\"isReadOnly\":false,\"hasDefaultValue\":true,\"type\":\"Boolean\",\"default\":false,\"isGenerated\":false,\"isUpdatedAt\":false},{\"name\":\"sipUsername\",\"kind\":\"scalar\",\"isList\":false,\"isRequired\":false,\"isUnique\":false,\"isId\":false,\"isReadOnly\":false,\"hasDefaultValue\":false,\"type\":\"String\",\"isGenerated\":false,\"isUpdatedAt\":false},{\"name\":\"sipPasswordEncrypted\",\"kind\":\"scalar\",\"isList\":false,\"isRequired\":false,\"isUnique\":false,\"isId\":false,\"isReadOnly\":false,\"hasDefaultValue\":false,\"type\":\"String\",\"isGenerated\":false,\"isUpdatedAt\":false},{\"name\":\"sipServer\",\"kind\":\"scalar\",\"isList\":false,\"isRequired\":false,\"isUnique\":false,\"isId\":false,\"isReadOnly\":false,\"hasDefaultValue\":false,\"type\":\"String\",\"isGenerated\":false,\"isUpdatedAt\":false}],\"primaryKey\":null,\"uniqueFields\":[],\"uniqueIndexes\":[],\"isGenerated\":false},\"MobileContractDetails\":{\"dbName\":null,\"fields\":[{\"name\":\"id\",\"kind\":\"scalar\",\"isList\":false,\"isRequired\":true,\"isUnique\":false,\"isId\":true,\"isReadOnly\":false,\"hasDefaultValue\":true,\"type\":\"Int\",\"default\":{\"name\":\"autoincrement\",\"args\":[]},\"isGenerated\":false,\"isUpdatedAt\":false},{\"name\":\"contractId\",\"kind\":\"scalar\",\"isList\":false,\"isRequired\":true,\"isUnique\":true,\"isId\":false,\"isReadOnly\":true,\"hasDefaultValue\":false,\"type\":\"Int\",\"isGenerated\":false,\"isUpdatedAt\":false},{\"name\":\"contract\",\"kind\":\"object\",\"isList\":false,\"isRequired\":true,\"isUnique\":false,\"isId\":false,\"isReadOnly\":false,\"hasDefaultValue\":false,\"type\":\"Contract\",\"relationName\":\"ContractToMobileContractDetails\",\"relationFromFields\":[\"contractId\"],\"relationToFields\":[\"id\"],\"relationOnDelete\":\"Cascade\",\"isGenerated\":false,\"isUpdatedAt\":false},{\"name\":\"requiresMultisim\",\"kind\":\"scalar\",\"isList\":false,\"isRequired\":true,\"isUnique\":false,\"isId\":false,\"isReadOnly\":false,\"hasDefaultValue\":true,\"type\":\"Boolean\",\"default\":false,\"isGenerated\":false,\"isUpdatedAt\":false},{\"name\":\"dataVolume\",\"kind\":\"scalar\",\"isList\":false,\"isRequired\":false,\"isUnique\":false,\"isId\":false,\"isReadOnly\":false,\"hasDefaultValue\":false,\"type\":\"Float\",\"isGenerated\":false,\"isUpdatedAt\":false},{\"name\":\"includedMinutes\",\"kind\":\"scalar\",\"isList\":false,\"isRequired\":false,\"isUnique\":false,\"isId\":false,\"isReadOnly\":false,\"hasDefaultValue\":false,\"type\":\"Int\",\"isGenerated\":false,\"isUpdatedAt\":false},{\"name\":\"includedSMS\",\"kind\":\"scalar\",\"isList\":false,\"isRequired\":false,\"isUnique\":false,\"isId\":false,\"isReadOnly\":false,\"hasDefaultValue\":false,\"type\":\"Int\",\"isGenerated\":false,\"isUpdatedAt\":false},{\"name\":\"deviceModel\",\"kind\":\"scalar\",\"isList\":false,\"isRequired\":false,\"isUnique\":false,\"isId\":false,\"isReadOnly\":false,\"hasDefaultValue\":false,\"type\":\"String\",\"isGenerated\":false,\"isUpdatedAt\":false},{\"name\":\"deviceImei\",\"kind\":\"scalar\",\"isList\":false,\"isRequired\":false,\"isUnique\":false,\"isId\":false,\"isReadOnly\":false,\"hasDefaultValue\":false,\"type\":\"String\",\"isGenerated\":false,\"isUpdatedAt\":false},{\"name\":\"simCards\",\"kind\":\"object\",\"isList\":true,\"isRequired\":true,\"isUnique\":false,\"isId\":false,\"isReadOnly\":false,\"hasDefaultValue\":false,\"type\":\"SimCard\",\"relationName\":\"MobileContractDetailsToSimCard\",\"relationFromFields\":[],\"relationToFields\":[],\"isGenerated\":false,\"isUpdatedAt\":false},{\"name\":\"phoneNumber\",\"kind\":\"scalar\",\"isList\":false,\"isRequired\":false,\"isUnique\":false,\"isId\":false,\"isReadOnly\":false,\"hasDefaultValue\":false,\"type\":\"String\",\"isGenerated\":false,\"isUpdatedAt\":false},{\"name\":\"simCardNumber\",\"kind\":\"scalar\",\"isList\":false,\"isRequired\":false,\"isUnique\":false,\"isId\":false,\"isReadOnly\":false,\"hasDefaultValue\":false,\"type\":\"String\",\"isGenerated\":false,\"isUpdatedAt\":false}],\"primaryKey\":null,\"uniqueFields\":[],\"uniqueIndexes\":[],\"isGenerated\":false},\"SimCard\":{\"dbName\":null,\"fields\":[{\"name\":\"id\",\"kind\":\"scalar\",\"isList\":false,\"isRequired\":true,\"isUnique\":false,\"isId\":true,\"isReadOnly\":false,\"hasDefaultValue\":true,\"type\":\"Int\",\"default\":{\"name\":\"autoincrement\",\"args\":[]},\"isGenerated\":false,\"isUpdatedAt\":false},{\"name\":\"mobileDetailsId\",\"kind\":\"scalar\",\"isList\":false,\"isRequired\":true,\"isUnique\":false,\"isId\":false,\"isReadOnly\":true,\"hasDefaultValue\":false,\"type\":\"Int\",\"isGenerated\":false,\"isUpdatedAt\":false},{\"name\":\"mobileDetails\",\"kind\":\"object\",\"isList\":false,\"isRequired\":true,\"isUnique\":false,\"isId\":false,\"isReadOnly\":false,\"hasDefaultValue\":false,\"type\":\"MobileContractDetails\",\"relationName\":\"MobileContractDetailsToSimCard\",\"relationFromFields\":[\"mobileDetailsId\"],\"relationToFields\":[\"id\"],\"relationOnDelete\":\"Cascade\",\"isGenerated\":false,\"isUpdatedAt\":false},{\"name\":\"phoneNumber\",\"kind\":\"scalar\",\"isList\":false,\"isRequired\":false,\"isUnique\":false,\"isId\":false,\"isReadOnly\":false,\"hasDefaultValue\":false,\"type\":\"String\",\"isGenerated\":false,\"isUpdatedAt\":false},{\"name\":\"simCardNumber\",\"kind\":\"scalar\",\"isList\":false,\"isRequired\":false,\"isUnique\":false,\"isId\":false,\"isReadOnly\":false,\"hasDefaultValue\":false,\"type\":\"String\",\"isGenerated\":false,\"isUpdatedAt\":false},{\"name\":\"pin\",\"kind\":\"scalar\",\"isList\":false,\"isRequired\":false,\"isUnique\":false,\"isId\":false,\"isReadOnly\":false,\"hasDefaultValue\":false,\"type\":\"String\",\"isGenerated\":false,\"isUpdatedAt\":false},{\"name\":\"puk\",\"kind\":\"scalar\",\"isList\":false,\"isRequired\":false,\"isUnique\":false,\"isId\":false,\"isReadOnly\":false,\"hasDefaultValue\":false,\"type\":\"String\",\"isGenerated\":false,\"isUpdatedAt\":false},{\"name\":\"isMultisim\",\"kind\":\"scalar\",\"isList\":false,\"isRequired\":true,\"isUnique\":false,\"isId\":false,\"isReadOnly\":false,\"hasDefaultValue\":true,\"type\":\"Boolean\",\"default\":false,\"isGenerated\":false,\"isUpdatedAt\":false},{\"name\":\"isMain\",\"kind\":\"scalar\",\"isList\":false,\"isRequired\":true,\"isUnique\":false,\"isId\":false,\"isReadOnly\":false,\"hasDefaultValue\":true,\"type\":\"Boolean\",\"default\":false,\"isGenerated\":false,\"isUpdatedAt\":false},{\"name\":\"createdAt\",\"kind\":\"scalar\",\"isList\":false,\"isRequired\":true,\"isUnique\":false,\"isId\":false,\"isReadOnly\":false,\"hasDefaultValue\":true,\"type\":\"DateTime\",\"default\":{\"name\":\"now\",\"args\":[]},\"isGenerated\":false,\"isUpdatedAt\":false},{\"name\":\"updatedAt\",\"kind\":\"scalar\",\"isList\":false,\"isRequired\":true,\"isUnique\":false,\"isId\":false,\"isReadOnly\":false,\"hasDefaultValue\":false,\"type\":\"DateTime\",\"isGenerated\":false,\"isUpdatedAt\":true}],\"primaryKey\":null,\"uniqueFields\":[],\"uniqueIndexes\":[],\"isGenerated\":false},\"TvContractDetails\":{\"dbName\":null,\"fields\":[{\"name\":\"id\",\"kind\":\"scalar\",\"isList\":false,\"isRequired\":true,\"isUnique\":false,\"isId\":true,\"isReadOnly\":false,\"hasDefaultValue\":true,\"type\":\"Int\",\"default\":{\"name\":\"autoincrement\",\"args\":[]},\"isGenerated\":false,\"isUpdatedAt\":false},{\"name\":\"contractId\",\"kind\":\"scalar\",\"isList\":false,\"isRequired\":true,\"isUnique\":true,\"isId\":false,\"isReadOnly\":true,\"hasDefaultValue\":false,\"type\":\"Int\",\"isGenerated\":false,\"isUpdatedAt\":false},{\"name\":\"contract\",\"kind\":\"object\",\"isList\":false,\"isRequired\":true,\"isUnique\":false,\"isId\":false,\"isReadOnly\":false,\"hasDefaultValue\":false,\"type\":\"Contract\",\"relationName\":\"ContractToTvContractDetails\",\"relationFromFields\":[\"contractId\"],\"relationToFields\":[\"id\"],\"relationOnDelete\":\"Cascade\",\"isGenerated\":false,\"isUpdatedAt\":false},{\"name\":\"receiverModel\",\"kind\":\"scalar\",\"isList\":false,\"isRequired\":false,\"isUnique\":false,\"isId\":false,\"isReadOnly\":false,\"hasDefaultValue\":false,\"type\":\"String\",\"isGenerated\":false,\"isUpdatedAt\":false},{\"name\":\"smartcardNumber\",\"kind\":\"scalar\",\"isList\":false,\"isRequired\":false,\"isUnique\":false,\"isId\":false,\"isReadOnly\":false,\"hasDefaultValue\":false,\"type\":\"String\",\"isGenerated\":false,\"isUpdatedAt\":false},{\"name\":\"package\",\"kind\":\"scalar\",\"isList\":false,\"isRequired\":false,\"isUnique\":false,\"isId\":false,\"isReadOnly\":false,\"hasDefaultValue\":false,\"type\":\"String\",\"isGenerated\":false,\"isUpdatedAt\":false}],\"primaryKey\":null,\"uniqueFields\":[],\"uniqueIndexes\":[],\"isGenerated\":false},\"CarInsuranceDetails\":{\"dbName\":null,\"fields\":[{\"name\":\"id\",\"kind\":\"scalar\",\"isList\":false,\"isRequired\":true,\"isUnique\":false,\"isId\":true,\"isReadOnly\":false,\"hasDefaultValue\":true,\"type\":\"Int\",\"default\":{\"name\":\"autoincrement\",\"args\":[]},\"isGenerated\":false,\"isUpdatedAt\":false},{\"name\":\"contractId\",\"kind\":\"scalar\",\"isList\":false,\"isRequired\":true,\"isUnique\":true,\"isId\":false,\"isReadOnly\":true,\"hasDefaultValue\":false,\"type\":\"Int\",\"isGenerated\":false,\"isUpdatedAt\":false},{\"name\":\"contract\",\"kind\":\"object\",\"isList\":false,\"isRequired\":true,\"isUnique\":false,\"isId\":false,\"isReadOnly\":false,\"hasDefaultValue\":false,\"type\":\"Contract\",\"relationName\":\"CarInsuranceDetailsToContract\",\"relationFromFields\":[\"contractId\"],\"relationToFields\":[\"id\"],\"relationOnDelete\":\"Cascade\",\"isGenerated\":false,\"isUpdatedAt\":false},{\"name\":\"licensePlate\",\"kind\":\"scalar\",\"isList\":false,\"isRequired\":false,\"isUnique\":false,\"isId\":false,\"isReadOnly\":false,\"hasDefaultValue\":false,\"type\":\"String\",\"isGenerated\":false,\"isUpdatedAt\":false},{\"name\":\"hsn\",\"kind\":\"scalar\",\"isList\":false,\"isRequired\":false,\"isUnique\":false,\"isId\":false,\"isReadOnly\":false,\"hasDefaultValue\":false,\"type\":\"String\",\"isGenerated\":false,\"isUpdatedAt\":false},{\"name\":\"tsn\",\"kind\":\"scalar\",\"isList\":false,\"isRequired\":false,\"isUnique\":false,\"isId\":false,\"isReadOnly\":false,\"hasDefaultValue\":false,\"type\":\"String\",\"isGenerated\":false,\"isUpdatedAt\":false},{\"name\":\"vin\",\"kind\":\"scalar\",\"isList\":false,\"isRequired\":false,\"isUnique\":false,\"isId\":false,\"isReadOnly\":false,\"hasDefaultValue\":false,\"type\":\"String\",\"isGenerated\":false,\"isUpdatedAt\":false},{\"name\":\"vehicleType\",\"kind\":\"scalar\",\"isList\":false,\"isRequired\":false,\"isUnique\":false,\"isId\":false,\"isReadOnly\":false,\"hasDefaultValue\":false,\"type\":\"String\",\"isGenerated\":false,\"isUpdatedAt\":false},{\"name\":\"firstRegistration\",\"kind\":\"scalar\",\"isList\":false,\"isRequired\":false,\"isUnique\":false,\"isId\":false,\"isReadOnly\":false,\"hasDefaultValue\":false,\"type\":\"DateTime\",\"isGenerated\":false,\"isUpdatedAt\":false},{\"name\":\"noClaimsClass\",\"kind\":\"scalar\",\"isList\":false,\"isRequired\":false,\"isUnique\":false,\"isId\":false,\"isReadOnly\":false,\"hasDefaultValue\":false,\"type\":\"String\",\"isGenerated\":false,\"isUpdatedAt\":false},{\"name\":\"insuranceType\",\"kind\":\"enum\",\"isList\":false,\"isRequired\":true,\"isUnique\":false,\"isId\":false,\"isReadOnly\":false,\"hasDefaultValue\":true,\"type\":\"InsuranceType\",\"default\":\"LIABILITY\",\"isGenerated\":false,\"isUpdatedAt\":false},{\"name\":\"deductiblePartial\",\"kind\":\"scalar\",\"isList\":false,\"isRequired\":false,\"isUnique\":false,\"isId\":false,\"isReadOnly\":false,\"hasDefaultValue\":false,\"type\":\"Float\",\"isGenerated\":false,\"isUpdatedAt\":false},{\"name\":\"deductibleFull\",\"kind\":\"scalar\",\"isList\":false,\"isRequired\":false,\"isUnique\":false,\"isId\":false,\"isReadOnly\":false,\"hasDefaultValue\":false,\"type\":\"Float\",\"isGenerated\":false,\"isUpdatedAt\":false},{\"name\":\"policyNumber\",\"kind\":\"scalar\",\"isList\":false,\"isRequired\":false,\"isUnique\":false,\"isId\":false,\"isReadOnly\":false,\"hasDefaultValue\":false,\"type\":\"String\",\"isGenerated\":false,\"isUpdatedAt\":false},{\"name\":\"previousInsurer\",\"kind\":\"scalar\",\"isList\":false,\"isRequired\":false,\"isUnique\":false,\"isId\":false,\"isReadOnly\":false,\"hasDefaultValue\":false,\"type\":\"String\",\"isGenerated\":false,\"isUpdatedAt\":false}],\"primaryKey\":null,\"uniqueFields\":[],\"uniqueIndexes\":[],\"isGenerated\":false}},\"enums\":{\"CustomerType\":{\"values\":[{\"name\":\"PRIVATE\",\"dbName\":null},{\"name\":\"BUSINESS\",\"dbName\":null}],\"dbName\":null},\"AddressType\":{\"values\":[{\"name\":\"DELIVERY_RESIDENCE\",\"dbName\":null},{\"name\":\"BILLING\",\"dbName\":null}],\"dbName\":null},\"DocumentType\":{\"values\":[{\"name\":\"ID_CARD\",\"dbName\":null},{\"name\":\"PASSPORT\",\"dbName\":null},{\"name\":\"DRIVERS_LICENSE\",\"dbName\":null},{\"name\":\"OTHER\",\"dbName\":null}],\"dbName\":null},\"EmailProviderType\":{\"values\":[{\"name\":\"PLESK\",\"dbName\":null},{\"name\":\"CPANEL\",\"dbName\":null},{\"name\":\"DIRECTADMIN\",\"dbName\":null}],\"dbName\":null},\"MeterType\":{\"values\":[{\"name\":\"ELECTRICITY\",\"dbName\":null},{\"name\":\"GAS\",\"dbName\":null}],\"dbName\":null},\"ContractType\":{\"values\":[{\"name\":\"ELECTRICITY\",\"dbName\":null},{\"name\":\"GAS\",\"dbName\":null},{\"name\":\"DSL\",\"dbName\":null},{\"name\":\"CABLE\",\"dbName\":null},{\"name\":\"FIBER\",\"dbName\":null},{\"name\":\"MOBILE\",\"dbName\":null},{\"name\":\"TV\",\"dbName\":null},{\"name\":\"CAR_INSURANCE\",\"dbName\":null}],\"dbName\":null},\"ContractStatus\":{\"values\":[{\"name\":\"DRAFT\",\"dbName\":null},{\"name\":\"PENDING\",\"dbName\":null},{\"name\":\"ACTIVE\",\"dbName\":null},{\"name\":\"CANCELLED\",\"dbName\":null},{\"name\":\"EXPIRED\",\"dbName\":null},{\"name\":\"DEACTIVATED\",\"dbName\":null}],\"dbName\":null},\"ContractTaskStatus\":{\"values\":[{\"name\":\"OPEN\",\"dbName\":null},{\"name\":\"COMPLETED\",\"dbName\":null}],\"dbName\":null},\"InsuranceType\":{\"values\":[{\"name\":\"LIABILITY\",\"dbName\":null},{\"name\":\"PARTIAL\",\"dbName\":null},{\"name\":\"FULL\",\"dbName\":null}],\"dbName\":null}},\"types\":{}}") +config.runtimeDataModel = JSON.parse("{\"models\":{\"AppSetting\":{\"dbName\":null,\"fields\":[{\"name\":\"id\",\"kind\":\"scalar\",\"isList\":false,\"isRequired\":true,\"isUnique\":false,\"isId\":true,\"isReadOnly\":false,\"hasDefaultValue\":true,\"type\":\"Int\",\"default\":{\"name\":\"autoincrement\",\"args\":[]},\"isGenerated\":false,\"isUpdatedAt\":false},{\"name\":\"key\",\"kind\":\"scalar\",\"isList\":false,\"isRequired\":true,\"isUnique\":true,\"isId\":false,\"isReadOnly\":false,\"hasDefaultValue\":false,\"type\":\"String\",\"isGenerated\":false,\"isUpdatedAt\":false},{\"name\":\"value\",\"kind\":\"scalar\",\"isList\":false,\"isRequired\":true,\"isUnique\":false,\"isId\":false,\"isReadOnly\":false,\"hasDefaultValue\":false,\"type\":\"String\",\"isGenerated\":false,\"isUpdatedAt\":false},{\"name\":\"createdAt\",\"kind\":\"scalar\",\"isList\":false,\"isRequired\":true,\"isUnique\":false,\"isId\":false,\"isReadOnly\":false,\"hasDefaultValue\":true,\"type\":\"DateTime\",\"default\":{\"name\":\"now\",\"args\":[]},\"isGenerated\":false,\"isUpdatedAt\":false},{\"name\":\"updatedAt\",\"kind\":\"scalar\",\"isList\":false,\"isRequired\":true,\"isUnique\":false,\"isId\":false,\"isReadOnly\":false,\"hasDefaultValue\":false,\"type\":\"DateTime\",\"isGenerated\":false,\"isUpdatedAt\":true}],\"primaryKey\":null,\"uniqueFields\":[],\"uniqueIndexes\":[],\"isGenerated\":false},\"User\":{\"dbName\":null,\"fields\":[{\"name\":\"id\",\"kind\":\"scalar\",\"isList\":false,\"isRequired\":true,\"isUnique\":false,\"isId\":true,\"isReadOnly\":false,\"hasDefaultValue\":true,\"type\":\"Int\",\"default\":{\"name\":\"autoincrement\",\"args\":[]},\"isGenerated\":false,\"isUpdatedAt\":false},{\"name\":\"email\",\"kind\":\"scalar\",\"isList\":false,\"isRequired\":true,\"isUnique\":true,\"isId\":false,\"isReadOnly\":false,\"hasDefaultValue\":false,\"type\":\"String\",\"isGenerated\":false,\"isUpdatedAt\":false},{\"name\":\"password\",\"kind\":\"scalar\",\"isList\":false,\"isRequired\":true,\"isUnique\":false,\"isId\":false,\"isReadOnly\":false,\"hasDefaultValue\":false,\"type\":\"String\",\"isGenerated\":false,\"isUpdatedAt\":false},{\"name\":\"firstName\",\"kind\":\"scalar\",\"isList\":false,\"isRequired\":true,\"isUnique\":false,\"isId\":false,\"isReadOnly\":false,\"hasDefaultValue\":false,\"type\":\"String\",\"isGenerated\":false,\"isUpdatedAt\":false},{\"name\":\"lastName\",\"kind\":\"scalar\",\"isList\":false,\"isRequired\":true,\"isUnique\":false,\"isId\":false,\"isReadOnly\":false,\"hasDefaultValue\":false,\"type\":\"String\",\"isGenerated\":false,\"isUpdatedAt\":false},{\"name\":\"isActive\",\"kind\":\"scalar\",\"isList\":false,\"isRequired\":true,\"isUnique\":false,\"isId\":false,\"isReadOnly\":false,\"hasDefaultValue\":true,\"type\":\"Boolean\",\"default\":true,\"isGenerated\":false,\"isUpdatedAt\":false},{\"name\":\"tokenInvalidatedAt\",\"kind\":\"scalar\",\"isList\":false,\"isRequired\":false,\"isUnique\":false,\"isId\":false,\"isReadOnly\":false,\"hasDefaultValue\":false,\"type\":\"DateTime\",\"isGenerated\":false,\"isUpdatedAt\":false},{\"name\":\"customerId\",\"kind\":\"scalar\",\"isList\":false,\"isRequired\":false,\"isUnique\":true,\"isId\":false,\"isReadOnly\":true,\"hasDefaultValue\":false,\"type\":\"Int\",\"isGenerated\":false,\"isUpdatedAt\":false},{\"name\":\"customer\",\"kind\":\"object\",\"isList\":false,\"isRequired\":false,\"isUnique\":false,\"isId\":false,\"isReadOnly\":false,\"hasDefaultValue\":false,\"type\":\"Customer\",\"relationName\":\"CustomerToUser\",\"relationFromFields\":[\"customerId\"],\"relationToFields\":[\"id\"],\"isGenerated\":false,\"isUpdatedAt\":false},{\"name\":\"roles\",\"kind\":\"object\",\"isList\":true,\"isRequired\":true,\"isUnique\":false,\"isId\":false,\"isReadOnly\":false,\"hasDefaultValue\":false,\"type\":\"UserRole\",\"relationName\":\"UserToUserRole\",\"relationFromFields\":[],\"relationToFields\":[],\"isGenerated\":false,\"isUpdatedAt\":false},{\"name\":\"createdAt\",\"kind\":\"scalar\",\"isList\":false,\"isRequired\":true,\"isUnique\":false,\"isId\":false,\"isReadOnly\":false,\"hasDefaultValue\":true,\"type\":\"DateTime\",\"default\":{\"name\":\"now\",\"args\":[]},\"isGenerated\":false,\"isUpdatedAt\":false},{\"name\":\"updatedAt\",\"kind\":\"scalar\",\"isList\":false,\"isRequired\":true,\"isUnique\":false,\"isId\":false,\"isReadOnly\":false,\"hasDefaultValue\":false,\"type\":\"DateTime\",\"isGenerated\":false,\"isUpdatedAt\":true}],\"primaryKey\":null,\"uniqueFields\":[],\"uniqueIndexes\":[],\"isGenerated\":false},\"Role\":{\"dbName\":null,\"fields\":[{\"name\":\"id\",\"kind\":\"scalar\",\"isList\":false,\"isRequired\":true,\"isUnique\":false,\"isId\":true,\"isReadOnly\":false,\"hasDefaultValue\":true,\"type\":\"Int\",\"default\":{\"name\":\"autoincrement\",\"args\":[]},\"isGenerated\":false,\"isUpdatedAt\":false},{\"name\":\"name\",\"kind\":\"scalar\",\"isList\":false,\"isRequired\":true,\"isUnique\":true,\"isId\":false,\"isReadOnly\":false,\"hasDefaultValue\":false,\"type\":\"String\",\"isGenerated\":false,\"isUpdatedAt\":false},{\"name\":\"description\",\"kind\":\"scalar\",\"isList\":false,\"isRequired\":false,\"isUnique\":false,\"isId\":false,\"isReadOnly\":false,\"hasDefaultValue\":false,\"type\":\"String\",\"isGenerated\":false,\"isUpdatedAt\":false},{\"name\":\"permissions\",\"kind\":\"object\",\"isList\":true,\"isRequired\":true,\"isUnique\":false,\"isId\":false,\"isReadOnly\":false,\"hasDefaultValue\":false,\"type\":\"RolePermission\",\"relationName\":\"RoleToRolePermission\",\"relationFromFields\":[],\"relationToFields\":[],\"isGenerated\":false,\"isUpdatedAt\":false},{\"name\":\"users\",\"kind\":\"object\",\"isList\":true,\"isRequired\":true,\"isUnique\":false,\"isId\":false,\"isReadOnly\":false,\"hasDefaultValue\":false,\"type\":\"UserRole\",\"relationName\":\"RoleToUserRole\",\"relationFromFields\":[],\"relationToFields\":[],\"isGenerated\":false,\"isUpdatedAt\":false},{\"name\":\"createdAt\",\"kind\":\"scalar\",\"isList\":false,\"isRequired\":true,\"isUnique\":false,\"isId\":false,\"isReadOnly\":false,\"hasDefaultValue\":true,\"type\":\"DateTime\",\"default\":{\"name\":\"now\",\"args\":[]},\"isGenerated\":false,\"isUpdatedAt\":false},{\"name\":\"updatedAt\",\"kind\":\"scalar\",\"isList\":false,\"isRequired\":true,\"isUnique\":false,\"isId\":false,\"isReadOnly\":false,\"hasDefaultValue\":false,\"type\":\"DateTime\",\"isGenerated\":false,\"isUpdatedAt\":true}],\"primaryKey\":null,\"uniqueFields\":[],\"uniqueIndexes\":[],\"isGenerated\":false},\"Permission\":{\"dbName\":null,\"fields\":[{\"name\":\"id\",\"kind\":\"scalar\",\"isList\":false,\"isRequired\":true,\"isUnique\":false,\"isId\":true,\"isReadOnly\":false,\"hasDefaultValue\":true,\"type\":\"Int\",\"default\":{\"name\":\"autoincrement\",\"args\":[]},\"isGenerated\":false,\"isUpdatedAt\":false},{\"name\":\"resource\",\"kind\":\"scalar\",\"isList\":false,\"isRequired\":true,\"isUnique\":false,\"isId\":false,\"isReadOnly\":false,\"hasDefaultValue\":false,\"type\":\"String\",\"isGenerated\":false,\"isUpdatedAt\":false},{\"name\":\"action\",\"kind\":\"scalar\",\"isList\":false,\"isRequired\":true,\"isUnique\":false,\"isId\":false,\"isReadOnly\":false,\"hasDefaultValue\":false,\"type\":\"String\",\"isGenerated\":false,\"isUpdatedAt\":false},{\"name\":\"roles\",\"kind\":\"object\",\"isList\":true,\"isRequired\":true,\"isUnique\":false,\"isId\":false,\"isReadOnly\":false,\"hasDefaultValue\":false,\"type\":\"RolePermission\",\"relationName\":\"PermissionToRolePermission\",\"relationFromFields\":[],\"relationToFields\":[],\"isGenerated\":false,\"isUpdatedAt\":false}],\"primaryKey\":null,\"uniqueFields\":[[\"resource\",\"action\"]],\"uniqueIndexes\":[{\"name\":null,\"fields\":[\"resource\",\"action\"]}],\"isGenerated\":false},\"RolePermission\":{\"dbName\":null,\"fields\":[{\"name\":\"roleId\",\"kind\":\"scalar\",\"isList\":false,\"isRequired\":true,\"isUnique\":false,\"isId\":false,\"isReadOnly\":true,\"hasDefaultValue\":false,\"type\":\"Int\",\"isGenerated\":false,\"isUpdatedAt\":false},{\"name\":\"permissionId\",\"kind\":\"scalar\",\"isList\":false,\"isRequired\":true,\"isUnique\":false,\"isId\":false,\"isReadOnly\":true,\"hasDefaultValue\":false,\"type\":\"Int\",\"isGenerated\":false,\"isUpdatedAt\":false},{\"name\":\"role\",\"kind\":\"object\",\"isList\":false,\"isRequired\":true,\"isUnique\":false,\"isId\":false,\"isReadOnly\":false,\"hasDefaultValue\":false,\"type\":\"Role\",\"relationName\":\"RoleToRolePermission\",\"relationFromFields\":[\"roleId\"],\"relationToFields\":[\"id\"],\"relationOnDelete\":\"Cascade\",\"isGenerated\":false,\"isUpdatedAt\":false},{\"name\":\"permission\",\"kind\":\"object\",\"isList\":false,\"isRequired\":true,\"isUnique\":false,\"isId\":false,\"isReadOnly\":false,\"hasDefaultValue\":false,\"type\":\"Permission\",\"relationName\":\"PermissionToRolePermission\",\"relationFromFields\":[\"permissionId\"],\"relationToFields\":[\"id\"],\"relationOnDelete\":\"Cascade\",\"isGenerated\":false,\"isUpdatedAt\":false}],\"primaryKey\":{\"name\":null,\"fields\":[\"roleId\",\"permissionId\"]},\"uniqueFields\":[],\"uniqueIndexes\":[],\"isGenerated\":false},\"UserRole\":{\"dbName\":null,\"fields\":[{\"name\":\"userId\",\"kind\":\"scalar\",\"isList\":false,\"isRequired\":true,\"isUnique\":false,\"isId\":false,\"isReadOnly\":true,\"hasDefaultValue\":false,\"type\":\"Int\",\"isGenerated\":false,\"isUpdatedAt\":false},{\"name\":\"roleId\",\"kind\":\"scalar\",\"isList\":false,\"isRequired\":true,\"isUnique\":false,\"isId\":false,\"isReadOnly\":true,\"hasDefaultValue\":false,\"type\":\"Int\",\"isGenerated\":false,\"isUpdatedAt\":false},{\"name\":\"user\",\"kind\":\"object\",\"isList\":false,\"isRequired\":true,\"isUnique\":false,\"isId\":false,\"isReadOnly\":false,\"hasDefaultValue\":false,\"type\":\"User\",\"relationName\":\"UserToUserRole\",\"relationFromFields\":[\"userId\"],\"relationToFields\":[\"id\"],\"relationOnDelete\":\"Cascade\",\"isGenerated\":false,\"isUpdatedAt\":false},{\"name\":\"role\",\"kind\":\"object\",\"isList\":false,\"isRequired\":true,\"isUnique\":false,\"isId\":false,\"isReadOnly\":false,\"hasDefaultValue\":false,\"type\":\"Role\",\"relationName\":\"RoleToUserRole\",\"relationFromFields\":[\"roleId\"],\"relationToFields\":[\"id\"],\"relationOnDelete\":\"Cascade\",\"isGenerated\":false,\"isUpdatedAt\":false}],\"primaryKey\":{\"name\":null,\"fields\":[\"userId\",\"roleId\"]},\"uniqueFields\":[],\"uniqueIndexes\":[],\"isGenerated\":false},\"Customer\":{\"dbName\":null,\"fields\":[{\"name\":\"id\",\"kind\":\"scalar\",\"isList\":false,\"isRequired\":true,\"isUnique\":false,\"isId\":true,\"isReadOnly\":false,\"hasDefaultValue\":true,\"type\":\"Int\",\"default\":{\"name\":\"autoincrement\",\"args\":[]},\"isGenerated\":false,\"isUpdatedAt\":false},{\"name\":\"customerNumber\",\"kind\":\"scalar\",\"isList\":false,\"isRequired\":true,\"isUnique\":true,\"isId\":false,\"isReadOnly\":false,\"hasDefaultValue\":false,\"type\":\"String\",\"isGenerated\":false,\"isUpdatedAt\":false},{\"name\":\"type\",\"kind\":\"enum\",\"isList\":false,\"isRequired\":true,\"isUnique\":false,\"isId\":false,\"isReadOnly\":false,\"hasDefaultValue\":true,\"type\":\"CustomerType\",\"default\":\"PRIVATE\",\"isGenerated\":false,\"isUpdatedAt\":false},{\"name\":\"salutation\",\"kind\":\"scalar\",\"isList\":false,\"isRequired\":false,\"isUnique\":false,\"isId\":false,\"isReadOnly\":false,\"hasDefaultValue\":false,\"type\":\"String\",\"isGenerated\":false,\"isUpdatedAt\":false},{\"name\":\"firstName\",\"kind\":\"scalar\",\"isList\":false,\"isRequired\":true,\"isUnique\":false,\"isId\":false,\"isReadOnly\":false,\"hasDefaultValue\":false,\"type\":\"String\",\"isGenerated\":false,\"isUpdatedAt\":false},{\"name\":\"lastName\",\"kind\":\"scalar\",\"isList\":false,\"isRequired\":true,\"isUnique\":false,\"isId\":false,\"isReadOnly\":false,\"hasDefaultValue\":false,\"type\":\"String\",\"isGenerated\":false,\"isUpdatedAt\":false},{\"name\":\"companyName\",\"kind\":\"scalar\",\"isList\":false,\"isRequired\":false,\"isUnique\":false,\"isId\":false,\"isReadOnly\":false,\"hasDefaultValue\":false,\"type\":\"String\",\"isGenerated\":false,\"isUpdatedAt\":false},{\"name\":\"foundingDate\",\"kind\":\"scalar\",\"isList\":false,\"isRequired\":false,\"isUnique\":false,\"isId\":false,\"isReadOnly\":false,\"hasDefaultValue\":false,\"type\":\"DateTime\",\"isGenerated\":false,\"isUpdatedAt\":false},{\"name\":\"birthDate\",\"kind\":\"scalar\",\"isList\":false,\"isRequired\":false,\"isUnique\":false,\"isId\":false,\"isReadOnly\":false,\"hasDefaultValue\":false,\"type\":\"DateTime\",\"isGenerated\":false,\"isUpdatedAt\":false},{\"name\":\"birthPlace\",\"kind\":\"scalar\",\"isList\":false,\"isRequired\":false,\"isUnique\":false,\"isId\":false,\"isReadOnly\":false,\"hasDefaultValue\":false,\"type\":\"String\",\"isGenerated\":false,\"isUpdatedAt\":false},{\"name\":\"email\",\"kind\":\"scalar\",\"isList\":false,\"isRequired\":false,\"isUnique\":false,\"isId\":false,\"isReadOnly\":false,\"hasDefaultValue\":false,\"type\":\"String\",\"isGenerated\":false,\"isUpdatedAt\":false},{\"name\":\"phone\",\"kind\":\"scalar\",\"isList\":false,\"isRequired\":false,\"isUnique\":false,\"isId\":false,\"isReadOnly\":false,\"hasDefaultValue\":false,\"type\":\"String\",\"isGenerated\":false,\"isUpdatedAt\":false},{\"name\":\"mobile\",\"kind\":\"scalar\",\"isList\":false,\"isRequired\":false,\"isUnique\":false,\"isId\":false,\"isReadOnly\":false,\"hasDefaultValue\":false,\"type\":\"String\",\"isGenerated\":false,\"isUpdatedAt\":false},{\"name\":\"taxNumber\",\"kind\":\"scalar\",\"isList\":false,\"isRequired\":false,\"isUnique\":false,\"isId\":false,\"isReadOnly\":false,\"hasDefaultValue\":false,\"type\":\"String\",\"isGenerated\":false,\"isUpdatedAt\":false},{\"name\":\"businessRegistrationPath\",\"kind\":\"scalar\",\"isList\":false,\"isRequired\":false,\"isUnique\":false,\"isId\":false,\"isReadOnly\":false,\"hasDefaultValue\":false,\"type\":\"String\",\"isGenerated\":false,\"isUpdatedAt\":false},{\"name\":\"commercialRegisterPath\",\"kind\":\"scalar\",\"isList\":false,\"isRequired\":false,\"isUnique\":false,\"isId\":false,\"isReadOnly\":false,\"hasDefaultValue\":false,\"type\":\"String\",\"isGenerated\":false,\"isUpdatedAt\":false},{\"name\":\"commercialRegisterNumber\",\"kind\":\"scalar\",\"isList\":false,\"isRequired\":false,\"isUnique\":false,\"isId\":false,\"isReadOnly\":false,\"hasDefaultValue\":false,\"type\":\"String\",\"isGenerated\":false,\"isUpdatedAt\":false},{\"name\":\"privacyPolicyPath\",\"kind\":\"scalar\",\"isList\":false,\"isRequired\":false,\"isUnique\":false,\"isId\":false,\"isReadOnly\":false,\"hasDefaultValue\":false,\"type\":\"String\",\"isGenerated\":false,\"isUpdatedAt\":false},{\"name\":\"notes\",\"kind\":\"scalar\",\"isList\":false,\"isRequired\":false,\"isUnique\":false,\"isId\":false,\"isReadOnly\":false,\"hasDefaultValue\":false,\"type\":\"String\",\"isGenerated\":false,\"isUpdatedAt\":false},{\"name\":\"portalEnabled\",\"kind\":\"scalar\",\"isList\":false,\"isRequired\":true,\"isUnique\":false,\"isId\":false,\"isReadOnly\":false,\"hasDefaultValue\":true,\"type\":\"Boolean\",\"default\":false,\"isGenerated\":false,\"isUpdatedAt\":false},{\"name\":\"portalEmail\",\"kind\":\"scalar\",\"isList\":false,\"isRequired\":false,\"isUnique\":true,\"isId\":false,\"isReadOnly\":false,\"hasDefaultValue\":false,\"type\":\"String\",\"isGenerated\":false,\"isUpdatedAt\":false},{\"name\":\"portalPasswordHash\",\"kind\":\"scalar\",\"isList\":false,\"isRequired\":false,\"isUnique\":false,\"isId\":false,\"isReadOnly\":false,\"hasDefaultValue\":false,\"type\":\"String\",\"isGenerated\":false,\"isUpdatedAt\":false},{\"name\":\"portalPasswordEncrypted\",\"kind\":\"scalar\",\"isList\":false,\"isRequired\":false,\"isUnique\":false,\"isId\":false,\"isReadOnly\":false,\"hasDefaultValue\":false,\"type\":\"String\",\"isGenerated\":false,\"isUpdatedAt\":false},{\"name\":\"portalLastLogin\",\"kind\":\"scalar\",\"isList\":false,\"isRequired\":false,\"isUnique\":false,\"isId\":false,\"isReadOnly\":false,\"hasDefaultValue\":false,\"type\":\"DateTime\",\"isGenerated\":false,\"isUpdatedAt\":false},{\"name\":\"user\",\"kind\":\"object\",\"isList\":false,\"isRequired\":false,\"isUnique\":false,\"isId\":false,\"isReadOnly\":false,\"hasDefaultValue\":false,\"type\":\"User\",\"relationName\":\"CustomerToUser\",\"relationFromFields\":[],\"relationToFields\":[],\"isGenerated\":false,\"isUpdatedAt\":false},{\"name\":\"addresses\",\"kind\":\"object\",\"isList\":true,\"isRequired\":true,\"isUnique\":false,\"isId\":false,\"isReadOnly\":false,\"hasDefaultValue\":false,\"type\":\"Address\",\"relationName\":\"AddressToCustomer\",\"relationFromFields\":[],\"relationToFields\":[],\"isGenerated\":false,\"isUpdatedAt\":false},{\"name\":\"bankCards\",\"kind\":\"object\",\"isList\":true,\"isRequired\":true,\"isUnique\":false,\"isId\":false,\"isReadOnly\":false,\"hasDefaultValue\":false,\"type\":\"BankCard\",\"relationName\":\"BankCardToCustomer\",\"relationFromFields\":[],\"relationToFields\":[],\"isGenerated\":false,\"isUpdatedAt\":false},{\"name\":\"identityDocuments\",\"kind\":\"object\",\"isList\":true,\"isRequired\":true,\"isUnique\":false,\"isId\":false,\"isReadOnly\":false,\"hasDefaultValue\":false,\"type\":\"IdentityDocument\",\"relationName\":\"CustomerToIdentityDocument\",\"relationFromFields\":[],\"relationToFields\":[],\"isGenerated\":false,\"isUpdatedAt\":false},{\"name\":\"meters\",\"kind\":\"object\",\"isList\":true,\"isRequired\":true,\"isUnique\":false,\"isId\":false,\"isReadOnly\":false,\"hasDefaultValue\":false,\"type\":\"Meter\",\"relationName\":\"CustomerToMeter\",\"relationFromFields\":[],\"relationToFields\":[],\"isGenerated\":false,\"isUpdatedAt\":false},{\"name\":\"stressfreiEmails\",\"kind\":\"object\",\"isList\":true,\"isRequired\":true,\"isUnique\":false,\"isId\":false,\"isReadOnly\":false,\"hasDefaultValue\":false,\"type\":\"StressfreiEmail\",\"relationName\":\"CustomerToStressfreiEmail\",\"relationFromFields\":[],\"relationToFields\":[],\"isGenerated\":false,\"isUpdatedAt\":false},{\"name\":\"contracts\",\"kind\":\"object\",\"isList\":true,\"isRequired\":true,\"isUnique\":false,\"isId\":false,\"isReadOnly\":false,\"hasDefaultValue\":false,\"type\":\"Contract\",\"relationName\":\"ContractToCustomer\",\"relationFromFields\":[],\"relationToFields\":[],\"isGenerated\":false,\"isUpdatedAt\":false},{\"name\":\"representingFor\",\"kind\":\"object\",\"isList\":true,\"isRequired\":true,\"isUnique\":false,\"isId\":false,\"isReadOnly\":false,\"hasDefaultValue\":false,\"type\":\"CustomerRepresentative\",\"relationName\":\"RepresentativeCustomer\",\"relationFromFields\":[],\"relationToFields\":[],\"isGenerated\":false,\"isUpdatedAt\":false},{\"name\":\"representedBy\",\"kind\":\"object\",\"isList\":true,\"isRequired\":true,\"isUnique\":false,\"isId\":false,\"isReadOnly\":false,\"hasDefaultValue\":false,\"type\":\"CustomerRepresentative\",\"relationName\":\"RepresentedCustomer\",\"relationFromFields\":[],\"relationToFields\":[],\"isGenerated\":false,\"isUpdatedAt\":false},{\"name\":\"createdAt\",\"kind\":\"scalar\",\"isList\":false,\"isRequired\":true,\"isUnique\":false,\"isId\":false,\"isReadOnly\":false,\"hasDefaultValue\":true,\"type\":\"DateTime\",\"default\":{\"name\":\"now\",\"args\":[]},\"isGenerated\":false,\"isUpdatedAt\":false},{\"name\":\"updatedAt\",\"kind\":\"scalar\",\"isList\":false,\"isRequired\":true,\"isUnique\":false,\"isId\":false,\"isReadOnly\":false,\"hasDefaultValue\":false,\"type\":\"DateTime\",\"isGenerated\":false,\"isUpdatedAt\":true}],\"primaryKey\":null,\"uniqueFields\":[],\"uniqueIndexes\":[],\"isGenerated\":false},\"CustomerRepresentative\":{\"dbName\":null,\"fields\":[{\"name\":\"id\",\"kind\":\"scalar\",\"isList\":false,\"isRequired\":true,\"isUnique\":false,\"isId\":true,\"isReadOnly\":false,\"hasDefaultValue\":true,\"type\":\"Int\",\"default\":{\"name\":\"autoincrement\",\"args\":[]},\"isGenerated\":false,\"isUpdatedAt\":false},{\"name\":\"customerId\",\"kind\":\"scalar\",\"isList\":false,\"isRequired\":true,\"isUnique\":false,\"isId\":false,\"isReadOnly\":true,\"hasDefaultValue\":false,\"type\":\"Int\",\"isGenerated\":false,\"isUpdatedAt\":false},{\"name\":\"customer\",\"kind\":\"object\",\"isList\":false,\"isRequired\":true,\"isUnique\":false,\"isId\":false,\"isReadOnly\":false,\"hasDefaultValue\":false,\"type\":\"Customer\",\"relationName\":\"RepresentedCustomer\",\"relationFromFields\":[\"customerId\"],\"relationToFields\":[\"id\"],\"relationOnDelete\":\"Cascade\",\"isGenerated\":false,\"isUpdatedAt\":false},{\"name\":\"representativeId\",\"kind\":\"scalar\",\"isList\":false,\"isRequired\":true,\"isUnique\":false,\"isId\":false,\"isReadOnly\":true,\"hasDefaultValue\":false,\"type\":\"Int\",\"isGenerated\":false,\"isUpdatedAt\":false},{\"name\":\"representative\",\"kind\":\"object\",\"isList\":false,\"isRequired\":true,\"isUnique\":false,\"isId\":false,\"isReadOnly\":false,\"hasDefaultValue\":false,\"type\":\"Customer\",\"relationName\":\"RepresentativeCustomer\",\"relationFromFields\":[\"representativeId\"],\"relationToFields\":[\"id\"],\"relationOnDelete\":\"Cascade\",\"isGenerated\":false,\"isUpdatedAt\":false},{\"name\":\"notes\",\"kind\":\"scalar\",\"isList\":false,\"isRequired\":false,\"isUnique\":false,\"isId\":false,\"isReadOnly\":false,\"hasDefaultValue\":false,\"type\":\"String\",\"isGenerated\":false,\"isUpdatedAt\":false},{\"name\":\"isActive\",\"kind\":\"scalar\",\"isList\":false,\"isRequired\":true,\"isUnique\":false,\"isId\":false,\"isReadOnly\":false,\"hasDefaultValue\":true,\"type\":\"Boolean\",\"default\":true,\"isGenerated\":false,\"isUpdatedAt\":false},{\"name\":\"createdAt\",\"kind\":\"scalar\",\"isList\":false,\"isRequired\":true,\"isUnique\":false,\"isId\":false,\"isReadOnly\":false,\"hasDefaultValue\":true,\"type\":\"DateTime\",\"default\":{\"name\":\"now\",\"args\":[]},\"isGenerated\":false,\"isUpdatedAt\":false},{\"name\":\"updatedAt\",\"kind\":\"scalar\",\"isList\":false,\"isRequired\":true,\"isUnique\":false,\"isId\":false,\"isReadOnly\":false,\"hasDefaultValue\":false,\"type\":\"DateTime\",\"isGenerated\":false,\"isUpdatedAt\":true}],\"primaryKey\":null,\"uniqueFields\":[[\"customerId\",\"representativeId\"]],\"uniqueIndexes\":[{\"name\":null,\"fields\":[\"customerId\",\"representativeId\"]}],\"isGenerated\":false},\"Address\":{\"dbName\":null,\"fields\":[{\"name\":\"id\",\"kind\":\"scalar\",\"isList\":false,\"isRequired\":true,\"isUnique\":false,\"isId\":true,\"isReadOnly\":false,\"hasDefaultValue\":true,\"type\":\"Int\",\"default\":{\"name\":\"autoincrement\",\"args\":[]},\"isGenerated\":false,\"isUpdatedAt\":false},{\"name\":\"customerId\",\"kind\":\"scalar\",\"isList\":false,\"isRequired\":true,\"isUnique\":false,\"isId\":false,\"isReadOnly\":true,\"hasDefaultValue\":false,\"type\":\"Int\",\"isGenerated\":false,\"isUpdatedAt\":false},{\"name\":\"customer\",\"kind\":\"object\",\"isList\":false,\"isRequired\":true,\"isUnique\":false,\"isId\":false,\"isReadOnly\":false,\"hasDefaultValue\":false,\"type\":\"Customer\",\"relationName\":\"AddressToCustomer\",\"relationFromFields\":[\"customerId\"],\"relationToFields\":[\"id\"],\"relationOnDelete\":\"Cascade\",\"isGenerated\":false,\"isUpdatedAt\":false},{\"name\":\"type\",\"kind\":\"enum\",\"isList\":false,\"isRequired\":true,\"isUnique\":false,\"isId\":false,\"isReadOnly\":false,\"hasDefaultValue\":true,\"type\":\"AddressType\",\"default\":\"DELIVERY_RESIDENCE\",\"isGenerated\":false,\"isUpdatedAt\":false},{\"name\":\"street\",\"kind\":\"scalar\",\"isList\":false,\"isRequired\":true,\"isUnique\":false,\"isId\":false,\"isReadOnly\":false,\"hasDefaultValue\":false,\"type\":\"String\",\"isGenerated\":false,\"isUpdatedAt\":false},{\"name\":\"houseNumber\",\"kind\":\"scalar\",\"isList\":false,\"isRequired\":true,\"isUnique\":false,\"isId\":false,\"isReadOnly\":false,\"hasDefaultValue\":false,\"type\":\"String\",\"isGenerated\":false,\"isUpdatedAt\":false},{\"name\":\"postalCode\",\"kind\":\"scalar\",\"isList\":false,\"isRequired\":true,\"isUnique\":false,\"isId\":false,\"isReadOnly\":false,\"hasDefaultValue\":false,\"type\":\"String\",\"isGenerated\":false,\"isUpdatedAt\":false},{\"name\":\"city\",\"kind\":\"scalar\",\"isList\":false,\"isRequired\":true,\"isUnique\":false,\"isId\":false,\"isReadOnly\":false,\"hasDefaultValue\":false,\"type\":\"String\",\"isGenerated\":false,\"isUpdatedAt\":false},{\"name\":\"country\",\"kind\":\"scalar\",\"isList\":false,\"isRequired\":true,\"isUnique\":false,\"isId\":false,\"isReadOnly\":false,\"hasDefaultValue\":true,\"type\":\"String\",\"default\":\"Deutschland\",\"isGenerated\":false,\"isUpdatedAt\":false},{\"name\":\"isDefault\",\"kind\":\"scalar\",\"isList\":false,\"isRequired\":true,\"isUnique\":false,\"isId\":false,\"isReadOnly\":false,\"hasDefaultValue\":true,\"type\":\"Boolean\",\"default\":false,\"isGenerated\":false,\"isUpdatedAt\":false},{\"name\":\"contracts\",\"kind\":\"object\",\"isList\":true,\"isRequired\":true,\"isUnique\":false,\"isId\":false,\"isReadOnly\":false,\"hasDefaultValue\":false,\"type\":\"Contract\",\"relationName\":\"AddressToContract\",\"relationFromFields\":[],\"relationToFields\":[],\"isGenerated\":false,\"isUpdatedAt\":false},{\"name\":\"createdAt\",\"kind\":\"scalar\",\"isList\":false,\"isRequired\":true,\"isUnique\":false,\"isId\":false,\"isReadOnly\":false,\"hasDefaultValue\":true,\"type\":\"DateTime\",\"default\":{\"name\":\"now\",\"args\":[]},\"isGenerated\":false,\"isUpdatedAt\":false},{\"name\":\"updatedAt\",\"kind\":\"scalar\",\"isList\":false,\"isRequired\":true,\"isUnique\":false,\"isId\":false,\"isReadOnly\":false,\"hasDefaultValue\":false,\"type\":\"DateTime\",\"isGenerated\":false,\"isUpdatedAt\":true}],\"primaryKey\":null,\"uniqueFields\":[],\"uniqueIndexes\":[],\"isGenerated\":false},\"BankCard\":{\"dbName\":null,\"fields\":[{\"name\":\"id\",\"kind\":\"scalar\",\"isList\":false,\"isRequired\":true,\"isUnique\":false,\"isId\":true,\"isReadOnly\":false,\"hasDefaultValue\":true,\"type\":\"Int\",\"default\":{\"name\":\"autoincrement\",\"args\":[]},\"isGenerated\":false,\"isUpdatedAt\":false},{\"name\":\"customerId\",\"kind\":\"scalar\",\"isList\":false,\"isRequired\":true,\"isUnique\":false,\"isId\":false,\"isReadOnly\":true,\"hasDefaultValue\":false,\"type\":\"Int\",\"isGenerated\":false,\"isUpdatedAt\":false},{\"name\":\"customer\",\"kind\":\"object\",\"isList\":false,\"isRequired\":true,\"isUnique\":false,\"isId\":false,\"isReadOnly\":false,\"hasDefaultValue\":false,\"type\":\"Customer\",\"relationName\":\"BankCardToCustomer\",\"relationFromFields\":[\"customerId\"],\"relationToFields\":[\"id\"],\"relationOnDelete\":\"Cascade\",\"isGenerated\":false,\"isUpdatedAt\":false},{\"name\":\"accountHolder\",\"kind\":\"scalar\",\"isList\":false,\"isRequired\":true,\"isUnique\":false,\"isId\":false,\"isReadOnly\":false,\"hasDefaultValue\":false,\"type\":\"String\",\"isGenerated\":false,\"isUpdatedAt\":false},{\"name\":\"iban\",\"kind\":\"scalar\",\"isList\":false,\"isRequired\":true,\"isUnique\":false,\"isId\":false,\"isReadOnly\":false,\"hasDefaultValue\":false,\"type\":\"String\",\"isGenerated\":false,\"isUpdatedAt\":false},{\"name\":\"bic\",\"kind\":\"scalar\",\"isList\":false,\"isRequired\":false,\"isUnique\":false,\"isId\":false,\"isReadOnly\":false,\"hasDefaultValue\":false,\"type\":\"String\",\"isGenerated\":false,\"isUpdatedAt\":false},{\"name\":\"bankName\",\"kind\":\"scalar\",\"isList\":false,\"isRequired\":false,\"isUnique\":false,\"isId\":false,\"isReadOnly\":false,\"hasDefaultValue\":false,\"type\":\"String\",\"isGenerated\":false,\"isUpdatedAt\":false},{\"name\":\"expiryDate\",\"kind\":\"scalar\",\"isList\":false,\"isRequired\":false,\"isUnique\":false,\"isId\":false,\"isReadOnly\":false,\"hasDefaultValue\":false,\"type\":\"DateTime\",\"isGenerated\":false,\"isUpdatedAt\":false},{\"name\":\"documentPath\",\"kind\":\"scalar\",\"isList\":false,\"isRequired\":false,\"isUnique\":false,\"isId\":false,\"isReadOnly\":false,\"hasDefaultValue\":false,\"type\":\"String\",\"isGenerated\":false,\"isUpdatedAt\":false},{\"name\":\"isActive\",\"kind\":\"scalar\",\"isList\":false,\"isRequired\":true,\"isUnique\":false,\"isId\":false,\"isReadOnly\":false,\"hasDefaultValue\":true,\"type\":\"Boolean\",\"default\":true,\"isGenerated\":false,\"isUpdatedAt\":false},{\"name\":\"contracts\",\"kind\":\"object\",\"isList\":true,\"isRequired\":true,\"isUnique\":false,\"isId\":false,\"isReadOnly\":false,\"hasDefaultValue\":false,\"type\":\"Contract\",\"relationName\":\"BankCardToContract\",\"relationFromFields\":[],\"relationToFields\":[],\"isGenerated\":false,\"isUpdatedAt\":false},{\"name\":\"createdAt\",\"kind\":\"scalar\",\"isList\":false,\"isRequired\":true,\"isUnique\":false,\"isId\":false,\"isReadOnly\":false,\"hasDefaultValue\":true,\"type\":\"DateTime\",\"default\":{\"name\":\"now\",\"args\":[]},\"isGenerated\":false,\"isUpdatedAt\":false},{\"name\":\"updatedAt\",\"kind\":\"scalar\",\"isList\":false,\"isRequired\":true,\"isUnique\":false,\"isId\":false,\"isReadOnly\":false,\"hasDefaultValue\":false,\"type\":\"DateTime\",\"isGenerated\":false,\"isUpdatedAt\":true}],\"primaryKey\":null,\"uniqueFields\":[],\"uniqueIndexes\":[],\"isGenerated\":false},\"IdentityDocument\":{\"dbName\":null,\"fields\":[{\"name\":\"id\",\"kind\":\"scalar\",\"isList\":false,\"isRequired\":true,\"isUnique\":false,\"isId\":true,\"isReadOnly\":false,\"hasDefaultValue\":true,\"type\":\"Int\",\"default\":{\"name\":\"autoincrement\",\"args\":[]},\"isGenerated\":false,\"isUpdatedAt\":false},{\"name\":\"customerId\",\"kind\":\"scalar\",\"isList\":false,\"isRequired\":true,\"isUnique\":false,\"isId\":false,\"isReadOnly\":true,\"hasDefaultValue\":false,\"type\":\"Int\",\"isGenerated\":false,\"isUpdatedAt\":false},{\"name\":\"customer\",\"kind\":\"object\",\"isList\":false,\"isRequired\":true,\"isUnique\":false,\"isId\":false,\"isReadOnly\":false,\"hasDefaultValue\":false,\"type\":\"Customer\",\"relationName\":\"CustomerToIdentityDocument\",\"relationFromFields\":[\"customerId\"],\"relationToFields\":[\"id\"],\"relationOnDelete\":\"Cascade\",\"isGenerated\":false,\"isUpdatedAt\":false},{\"name\":\"type\",\"kind\":\"enum\",\"isList\":false,\"isRequired\":true,\"isUnique\":false,\"isId\":false,\"isReadOnly\":false,\"hasDefaultValue\":true,\"type\":\"DocumentType\",\"default\":\"ID_CARD\",\"isGenerated\":false,\"isUpdatedAt\":false},{\"name\":\"documentNumber\",\"kind\":\"scalar\",\"isList\":false,\"isRequired\":true,\"isUnique\":false,\"isId\":false,\"isReadOnly\":false,\"hasDefaultValue\":false,\"type\":\"String\",\"isGenerated\":false,\"isUpdatedAt\":false},{\"name\":\"issuingAuthority\",\"kind\":\"scalar\",\"isList\":false,\"isRequired\":false,\"isUnique\":false,\"isId\":false,\"isReadOnly\":false,\"hasDefaultValue\":false,\"type\":\"String\",\"isGenerated\":false,\"isUpdatedAt\":false},{\"name\":\"issueDate\",\"kind\":\"scalar\",\"isList\":false,\"isRequired\":false,\"isUnique\":false,\"isId\":false,\"isReadOnly\":false,\"hasDefaultValue\":false,\"type\":\"DateTime\",\"isGenerated\":false,\"isUpdatedAt\":false},{\"name\":\"expiryDate\",\"kind\":\"scalar\",\"isList\":false,\"isRequired\":false,\"isUnique\":false,\"isId\":false,\"isReadOnly\":false,\"hasDefaultValue\":false,\"type\":\"DateTime\",\"isGenerated\":false,\"isUpdatedAt\":false},{\"name\":\"documentPath\",\"kind\":\"scalar\",\"isList\":false,\"isRequired\":false,\"isUnique\":false,\"isId\":false,\"isReadOnly\":false,\"hasDefaultValue\":false,\"type\":\"String\",\"isGenerated\":false,\"isUpdatedAt\":false},{\"name\":\"isActive\",\"kind\":\"scalar\",\"isList\":false,\"isRequired\":true,\"isUnique\":false,\"isId\":false,\"isReadOnly\":false,\"hasDefaultValue\":true,\"type\":\"Boolean\",\"default\":true,\"isGenerated\":false,\"isUpdatedAt\":false},{\"name\":\"licenseClasses\",\"kind\":\"scalar\",\"isList\":false,\"isRequired\":false,\"isUnique\":false,\"isId\":false,\"isReadOnly\":false,\"hasDefaultValue\":false,\"type\":\"String\",\"isGenerated\":false,\"isUpdatedAt\":false},{\"name\":\"licenseIssueDate\",\"kind\":\"scalar\",\"isList\":false,\"isRequired\":false,\"isUnique\":false,\"isId\":false,\"isReadOnly\":false,\"hasDefaultValue\":false,\"type\":\"DateTime\",\"isGenerated\":false,\"isUpdatedAt\":false},{\"name\":\"contracts\",\"kind\":\"object\",\"isList\":true,\"isRequired\":true,\"isUnique\":false,\"isId\":false,\"isReadOnly\":false,\"hasDefaultValue\":false,\"type\":\"Contract\",\"relationName\":\"ContractToIdentityDocument\",\"relationFromFields\":[],\"relationToFields\":[],\"isGenerated\":false,\"isUpdatedAt\":false},{\"name\":\"createdAt\",\"kind\":\"scalar\",\"isList\":false,\"isRequired\":true,\"isUnique\":false,\"isId\":false,\"isReadOnly\":false,\"hasDefaultValue\":true,\"type\":\"DateTime\",\"default\":{\"name\":\"now\",\"args\":[]},\"isGenerated\":false,\"isUpdatedAt\":false},{\"name\":\"updatedAt\",\"kind\":\"scalar\",\"isList\":false,\"isRequired\":true,\"isUnique\":false,\"isId\":false,\"isReadOnly\":false,\"hasDefaultValue\":false,\"type\":\"DateTime\",\"isGenerated\":false,\"isUpdatedAt\":true}],\"primaryKey\":null,\"uniqueFields\":[],\"uniqueIndexes\":[],\"isGenerated\":false},\"EmailProviderConfig\":{\"dbName\":null,\"fields\":[{\"name\":\"id\",\"kind\":\"scalar\",\"isList\":false,\"isRequired\":true,\"isUnique\":false,\"isId\":true,\"isReadOnly\":false,\"hasDefaultValue\":true,\"type\":\"Int\",\"default\":{\"name\":\"autoincrement\",\"args\":[]},\"isGenerated\":false,\"isUpdatedAt\":false},{\"name\":\"name\",\"kind\":\"scalar\",\"isList\":false,\"isRequired\":true,\"isUnique\":true,\"isId\":false,\"isReadOnly\":false,\"hasDefaultValue\":false,\"type\":\"String\",\"isGenerated\":false,\"isUpdatedAt\":false},{\"name\":\"type\",\"kind\":\"enum\",\"isList\":false,\"isRequired\":true,\"isUnique\":false,\"isId\":false,\"isReadOnly\":false,\"hasDefaultValue\":false,\"type\":\"EmailProviderType\",\"isGenerated\":false,\"isUpdatedAt\":false},{\"name\":\"apiUrl\",\"kind\":\"scalar\",\"isList\":false,\"isRequired\":true,\"isUnique\":false,\"isId\":false,\"isReadOnly\":false,\"hasDefaultValue\":false,\"type\":\"String\",\"isGenerated\":false,\"isUpdatedAt\":false},{\"name\":\"apiKey\",\"kind\":\"scalar\",\"isList\":false,\"isRequired\":false,\"isUnique\":false,\"isId\":false,\"isReadOnly\":false,\"hasDefaultValue\":false,\"type\":\"String\",\"isGenerated\":false,\"isUpdatedAt\":false},{\"name\":\"username\",\"kind\":\"scalar\",\"isList\":false,\"isRequired\":false,\"isUnique\":false,\"isId\":false,\"isReadOnly\":false,\"hasDefaultValue\":false,\"type\":\"String\",\"isGenerated\":false,\"isUpdatedAt\":false},{\"name\":\"passwordEncrypted\",\"kind\":\"scalar\",\"isList\":false,\"isRequired\":false,\"isUnique\":false,\"isId\":false,\"isReadOnly\":false,\"hasDefaultValue\":false,\"type\":\"String\",\"isGenerated\":false,\"isUpdatedAt\":false},{\"name\":\"domain\",\"kind\":\"scalar\",\"isList\":false,\"isRequired\":true,\"isUnique\":false,\"isId\":false,\"isReadOnly\":false,\"hasDefaultValue\":false,\"type\":\"String\",\"isGenerated\":false,\"isUpdatedAt\":false},{\"name\":\"defaultForwardEmail\",\"kind\":\"scalar\",\"isList\":false,\"isRequired\":false,\"isUnique\":false,\"isId\":false,\"isReadOnly\":false,\"hasDefaultValue\":false,\"type\":\"String\",\"isGenerated\":false,\"isUpdatedAt\":false},{\"name\":\"imapServer\",\"kind\":\"scalar\",\"isList\":false,\"isRequired\":false,\"isUnique\":false,\"isId\":false,\"isReadOnly\":false,\"hasDefaultValue\":false,\"type\":\"String\",\"isGenerated\":false,\"isUpdatedAt\":false},{\"name\":\"imapPort\",\"kind\":\"scalar\",\"isList\":false,\"isRequired\":false,\"isUnique\":false,\"isId\":false,\"isReadOnly\":false,\"hasDefaultValue\":true,\"type\":\"Int\",\"default\":993,\"isGenerated\":false,\"isUpdatedAt\":false},{\"name\":\"smtpServer\",\"kind\":\"scalar\",\"isList\":false,\"isRequired\":false,\"isUnique\":false,\"isId\":false,\"isReadOnly\":false,\"hasDefaultValue\":false,\"type\":\"String\",\"isGenerated\":false,\"isUpdatedAt\":false},{\"name\":\"smtpPort\",\"kind\":\"scalar\",\"isList\":false,\"isRequired\":false,\"isUnique\":false,\"isId\":false,\"isReadOnly\":false,\"hasDefaultValue\":true,\"type\":\"Int\",\"default\":465,\"isGenerated\":false,\"isUpdatedAt\":false},{\"name\":\"imapEncryption\",\"kind\":\"enum\",\"isList\":false,\"isRequired\":true,\"isUnique\":false,\"isId\":false,\"isReadOnly\":false,\"hasDefaultValue\":true,\"type\":\"MailEncryption\",\"default\":\"SSL\",\"isGenerated\":false,\"isUpdatedAt\":false},{\"name\":\"smtpEncryption\",\"kind\":\"enum\",\"isList\":false,\"isRequired\":true,\"isUnique\":false,\"isId\":false,\"isReadOnly\":false,\"hasDefaultValue\":true,\"type\":\"MailEncryption\",\"default\":\"SSL\",\"isGenerated\":false,\"isUpdatedAt\":false},{\"name\":\"allowSelfSignedCerts\",\"kind\":\"scalar\",\"isList\":false,\"isRequired\":true,\"isUnique\":false,\"isId\":false,\"isReadOnly\":false,\"hasDefaultValue\":true,\"type\":\"Boolean\",\"default\":false,\"isGenerated\":false,\"isUpdatedAt\":false},{\"name\":\"isActive\",\"kind\":\"scalar\",\"isList\":false,\"isRequired\":true,\"isUnique\":false,\"isId\":false,\"isReadOnly\":false,\"hasDefaultValue\":true,\"type\":\"Boolean\",\"default\":true,\"isGenerated\":false,\"isUpdatedAt\":false},{\"name\":\"isDefault\",\"kind\":\"scalar\",\"isList\":false,\"isRequired\":true,\"isUnique\":false,\"isId\":false,\"isReadOnly\":false,\"hasDefaultValue\":true,\"type\":\"Boolean\",\"default\":false,\"isGenerated\":false,\"isUpdatedAt\":false},{\"name\":\"createdAt\",\"kind\":\"scalar\",\"isList\":false,\"isRequired\":true,\"isUnique\":false,\"isId\":false,\"isReadOnly\":false,\"hasDefaultValue\":true,\"type\":\"DateTime\",\"default\":{\"name\":\"now\",\"args\":[]},\"isGenerated\":false,\"isUpdatedAt\":false},{\"name\":\"updatedAt\",\"kind\":\"scalar\",\"isList\":false,\"isRequired\":true,\"isUnique\":false,\"isId\":false,\"isReadOnly\":false,\"hasDefaultValue\":false,\"type\":\"DateTime\",\"isGenerated\":false,\"isUpdatedAt\":true}],\"primaryKey\":null,\"uniqueFields\":[],\"uniqueIndexes\":[],\"isGenerated\":false},\"StressfreiEmail\":{\"dbName\":null,\"fields\":[{\"name\":\"id\",\"kind\":\"scalar\",\"isList\":false,\"isRequired\":true,\"isUnique\":false,\"isId\":true,\"isReadOnly\":false,\"hasDefaultValue\":true,\"type\":\"Int\",\"default\":{\"name\":\"autoincrement\",\"args\":[]},\"isGenerated\":false,\"isUpdatedAt\":false},{\"name\":\"customerId\",\"kind\":\"scalar\",\"isList\":false,\"isRequired\":true,\"isUnique\":false,\"isId\":false,\"isReadOnly\":true,\"hasDefaultValue\":false,\"type\":\"Int\",\"isGenerated\":false,\"isUpdatedAt\":false},{\"name\":\"customer\",\"kind\":\"object\",\"isList\":false,\"isRequired\":true,\"isUnique\":false,\"isId\":false,\"isReadOnly\":false,\"hasDefaultValue\":false,\"type\":\"Customer\",\"relationName\":\"CustomerToStressfreiEmail\",\"relationFromFields\":[\"customerId\"],\"relationToFields\":[\"id\"],\"relationOnDelete\":\"Cascade\",\"isGenerated\":false,\"isUpdatedAt\":false},{\"name\":\"email\",\"kind\":\"scalar\",\"isList\":false,\"isRequired\":true,\"isUnique\":false,\"isId\":false,\"isReadOnly\":false,\"hasDefaultValue\":false,\"type\":\"String\",\"isGenerated\":false,\"isUpdatedAt\":false},{\"name\":\"platform\",\"kind\":\"scalar\",\"isList\":false,\"isRequired\":false,\"isUnique\":false,\"isId\":false,\"isReadOnly\":false,\"hasDefaultValue\":false,\"type\":\"String\",\"isGenerated\":false,\"isUpdatedAt\":false},{\"name\":\"notes\",\"kind\":\"scalar\",\"isList\":false,\"isRequired\":false,\"isUnique\":false,\"isId\":false,\"isReadOnly\":false,\"hasDefaultValue\":false,\"type\":\"String\",\"isGenerated\":false,\"isUpdatedAt\":false},{\"name\":\"isActive\",\"kind\":\"scalar\",\"isList\":false,\"isRequired\":true,\"isUnique\":false,\"isId\":false,\"isReadOnly\":false,\"hasDefaultValue\":true,\"type\":\"Boolean\",\"default\":true,\"isGenerated\":false,\"isUpdatedAt\":false},{\"name\":\"isProvisioned\",\"kind\":\"scalar\",\"isList\":false,\"isRequired\":true,\"isUnique\":false,\"isId\":false,\"isReadOnly\":false,\"hasDefaultValue\":true,\"type\":\"Boolean\",\"default\":false,\"isGenerated\":false,\"isUpdatedAt\":false},{\"name\":\"provisionedAt\",\"kind\":\"scalar\",\"isList\":false,\"isRequired\":false,\"isUnique\":false,\"isId\":false,\"isReadOnly\":false,\"hasDefaultValue\":false,\"type\":\"DateTime\",\"isGenerated\":false,\"isUpdatedAt\":false},{\"name\":\"provisionError\",\"kind\":\"scalar\",\"isList\":false,\"isRequired\":false,\"isUnique\":false,\"isId\":false,\"isReadOnly\":false,\"hasDefaultValue\":false,\"type\":\"String\",\"isGenerated\":false,\"isUpdatedAt\":false},{\"name\":\"hasMailbox\",\"kind\":\"scalar\",\"isList\":false,\"isRequired\":true,\"isUnique\":false,\"isId\":false,\"isReadOnly\":false,\"hasDefaultValue\":true,\"type\":\"Boolean\",\"default\":false,\"isGenerated\":false,\"isUpdatedAt\":false},{\"name\":\"emailPasswordEncrypted\",\"kind\":\"scalar\",\"isList\":false,\"isRequired\":false,\"isUnique\":false,\"isId\":false,\"isReadOnly\":false,\"hasDefaultValue\":false,\"type\":\"String\",\"isGenerated\":false,\"isUpdatedAt\":false},{\"name\":\"contracts\",\"kind\":\"object\",\"isList\":true,\"isRequired\":true,\"isUnique\":false,\"isId\":false,\"isReadOnly\":false,\"hasDefaultValue\":false,\"type\":\"Contract\",\"relationName\":\"ContractToStressfreiEmail\",\"relationFromFields\":[],\"relationToFields\":[],\"isGenerated\":false,\"isUpdatedAt\":false},{\"name\":\"cachedEmails\",\"kind\":\"object\",\"isList\":true,\"isRequired\":true,\"isUnique\":false,\"isId\":false,\"isReadOnly\":false,\"hasDefaultValue\":false,\"type\":\"CachedEmail\",\"relationName\":\"CachedEmailToStressfreiEmail\",\"relationFromFields\":[],\"relationToFields\":[],\"isGenerated\":false,\"isUpdatedAt\":false},{\"name\":\"createdAt\",\"kind\":\"scalar\",\"isList\":false,\"isRequired\":true,\"isUnique\":false,\"isId\":false,\"isReadOnly\":false,\"hasDefaultValue\":true,\"type\":\"DateTime\",\"default\":{\"name\":\"now\",\"args\":[]},\"isGenerated\":false,\"isUpdatedAt\":false},{\"name\":\"updatedAt\",\"kind\":\"scalar\",\"isList\":false,\"isRequired\":true,\"isUnique\":false,\"isId\":false,\"isReadOnly\":false,\"hasDefaultValue\":false,\"type\":\"DateTime\",\"isGenerated\":false,\"isUpdatedAt\":true}],\"primaryKey\":null,\"uniqueFields\":[],\"uniqueIndexes\":[],\"isGenerated\":false},\"CachedEmail\":{\"dbName\":null,\"fields\":[{\"name\":\"id\",\"kind\":\"scalar\",\"isList\":false,\"isRequired\":true,\"isUnique\":false,\"isId\":true,\"isReadOnly\":false,\"hasDefaultValue\":true,\"type\":\"Int\",\"default\":{\"name\":\"autoincrement\",\"args\":[]},\"isGenerated\":false,\"isUpdatedAt\":false},{\"name\":\"stressfreiEmailId\",\"kind\":\"scalar\",\"isList\":false,\"isRequired\":true,\"isUnique\":false,\"isId\":false,\"isReadOnly\":true,\"hasDefaultValue\":false,\"type\":\"Int\",\"isGenerated\":false,\"isUpdatedAt\":false},{\"name\":\"stressfreiEmail\",\"kind\":\"object\",\"isList\":false,\"isRequired\":true,\"isUnique\":false,\"isId\":false,\"isReadOnly\":false,\"hasDefaultValue\":false,\"type\":\"StressfreiEmail\",\"relationName\":\"CachedEmailToStressfreiEmail\",\"relationFromFields\":[\"stressfreiEmailId\"],\"relationToFields\":[\"id\"],\"relationOnDelete\":\"Cascade\",\"isGenerated\":false,\"isUpdatedAt\":false},{\"name\":\"folder\",\"kind\":\"enum\",\"isList\":false,\"isRequired\":true,\"isUnique\":false,\"isId\":false,\"isReadOnly\":false,\"hasDefaultValue\":true,\"type\":\"EmailFolder\",\"default\":\"INBOX\",\"isGenerated\":false,\"isUpdatedAt\":false},{\"name\":\"messageId\",\"kind\":\"scalar\",\"isList\":false,\"isRequired\":true,\"isUnique\":false,\"isId\":false,\"isReadOnly\":false,\"hasDefaultValue\":false,\"type\":\"String\",\"isGenerated\":false,\"isUpdatedAt\":false},{\"name\":\"uid\",\"kind\":\"scalar\",\"isList\":false,\"isRequired\":true,\"isUnique\":false,\"isId\":false,\"isReadOnly\":false,\"hasDefaultValue\":false,\"type\":\"Int\",\"isGenerated\":false,\"isUpdatedAt\":false},{\"name\":\"subject\",\"kind\":\"scalar\",\"isList\":false,\"isRequired\":false,\"isUnique\":false,\"isId\":false,\"isReadOnly\":false,\"hasDefaultValue\":false,\"type\":\"String\",\"isGenerated\":false,\"isUpdatedAt\":false},{\"name\":\"fromAddress\",\"kind\":\"scalar\",\"isList\":false,\"isRequired\":true,\"isUnique\":false,\"isId\":false,\"isReadOnly\":false,\"hasDefaultValue\":false,\"type\":\"String\",\"isGenerated\":false,\"isUpdatedAt\":false},{\"name\":\"fromName\",\"kind\":\"scalar\",\"isList\":false,\"isRequired\":false,\"isUnique\":false,\"isId\":false,\"isReadOnly\":false,\"hasDefaultValue\":false,\"type\":\"String\",\"isGenerated\":false,\"isUpdatedAt\":false},{\"name\":\"toAddresses\",\"kind\":\"scalar\",\"isList\":false,\"isRequired\":true,\"isUnique\":false,\"isId\":false,\"isReadOnly\":false,\"hasDefaultValue\":false,\"type\":\"String\",\"isGenerated\":false,\"isUpdatedAt\":false},{\"name\":\"ccAddresses\",\"kind\":\"scalar\",\"isList\":false,\"isRequired\":false,\"isUnique\":false,\"isId\":false,\"isReadOnly\":false,\"hasDefaultValue\":false,\"type\":\"String\",\"isGenerated\":false,\"isUpdatedAt\":false},{\"name\":\"receivedAt\",\"kind\":\"scalar\",\"isList\":false,\"isRequired\":true,\"isUnique\":false,\"isId\":false,\"isReadOnly\":false,\"hasDefaultValue\":false,\"type\":\"DateTime\",\"isGenerated\":false,\"isUpdatedAt\":false},{\"name\":\"textBody\",\"kind\":\"scalar\",\"isList\":false,\"isRequired\":false,\"isUnique\":false,\"isId\":false,\"isReadOnly\":false,\"hasDefaultValue\":false,\"type\":\"String\",\"isGenerated\":false,\"isUpdatedAt\":false},{\"name\":\"htmlBody\",\"kind\":\"scalar\",\"isList\":false,\"isRequired\":false,\"isUnique\":false,\"isId\":false,\"isReadOnly\":false,\"hasDefaultValue\":false,\"type\":\"String\",\"isGenerated\":false,\"isUpdatedAt\":false},{\"name\":\"hasAttachments\",\"kind\":\"scalar\",\"isList\":false,\"isRequired\":true,\"isUnique\":false,\"isId\":false,\"isReadOnly\":false,\"hasDefaultValue\":true,\"type\":\"Boolean\",\"default\":false,\"isGenerated\":false,\"isUpdatedAt\":false},{\"name\":\"attachmentNames\",\"kind\":\"scalar\",\"isList\":false,\"isRequired\":false,\"isUnique\":false,\"isId\":false,\"isReadOnly\":false,\"hasDefaultValue\":false,\"type\":\"String\",\"isGenerated\":false,\"isUpdatedAt\":false},{\"name\":\"contractId\",\"kind\":\"scalar\",\"isList\":false,\"isRequired\":false,\"isUnique\":false,\"isId\":false,\"isReadOnly\":true,\"hasDefaultValue\":false,\"type\":\"Int\",\"isGenerated\":false,\"isUpdatedAt\":false},{\"name\":\"contract\",\"kind\":\"object\",\"isList\":false,\"isRequired\":false,\"isUnique\":false,\"isId\":false,\"isReadOnly\":false,\"hasDefaultValue\":false,\"type\":\"Contract\",\"relationName\":\"CachedEmailToContract\",\"relationFromFields\":[\"contractId\"],\"relationToFields\":[\"id\"],\"relationOnDelete\":\"SetNull\",\"isGenerated\":false,\"isUpdatedAt\":false},{\"name\":\"assignedAt\",\"kind\":\"scalar\",\"isList\":false,\"isRequired\":false,\"isUnique\":false,\"isId\":false,\"isReadOnly\":false,\"hasDefaultValue\":false,\"type\":\"DateTime\",\"isGenerated\":false,\"isUpdatedAt\":false},{\"name\":\"assignedBy\",\"kind\":\"scalar\",\"isList\":false,\"isRequired\":false,\"isUnique\":false,\"isId\":false,\"isReadOnly\":false,\"hasDefaultValue\":false,\"type\":\"Int\",\"isGenerated\":false,\"isUpdatedAt\":false},{\"name\":\"isAutoAssigned\",\"kind\":\"scalar\",\"isList\":false,\"isRequired\":true,\"isUnique\":false,\"isId\":false,\"isReadOnly\":false,\"hasDefaultValue\":true,\"type\":\"Boolean\",\"default\":false,\"isGenerated\":false,\"isUpdatedAt\":false},{\"name\":\"isRead\",\"kind\":\"scalar\",\"isList\":false,\"isRequired\":true,\"isUnique\":false,\"isId\":false,\"isReadOnly\":false,\"hasDefaultValue\":true,\"type\":\"Boolean\",\"default\":false,\"isGenerated\":false,\"isUpdatedAt\":false},{\"name\":\"isStarred\",\"kind\":\"scalar\",\"isList\":false,\"isRequired\":true,\"isUnique\":false,\"isId\":false,\"isReadOnly\":false,\"hasDefaultValue\":true,\"type\":\"Boolean\",\"default\":false,\"isGenerated\":false,\"isUpdatedAt\":false},{\"name\":\"isDeleted\",\"kind\":\"scalar\",\"isList\":false,\"isRequired\":true,\"isUnique\":false,\"isId\":false,\"isReadOnly\":false,\"hasDefaultValue\":true,\"type\":\"Boolean\",\"default\":false,\"isGenerated\":false,\"isUpdatedAt\":false},{\"name\":\"deletedAt\",\"kind\":\"scalar\",\"isList\":false,\"isRequired\":false,\"isUnique\":false,\"isId\":false,\"isReadOnly\":false,\"hasDefaultValue\":false,\"type\":\"DateTime\",\"isGenerated\":false,\"isUpdatedAt\":false},{\"name\":\"createdAt\",\"kind\":\"scalar\",\"isList\":false,\"isRequired\":true,\"isUnique\":false,\"isId\":false,\"isReadOnly\":false,\"hasDefaultValue\":true,\"type\":\"DateTime\",\"default\":{\"name\":\"now\",\"args\":[]},\"isGenerated\":false,\"isUpdatedAt\":false},{\"name\":\"updatedAt\",\"kind\":\"scalar\",\"isList\":false,\"isRequired\":true,\"isUnique\":false,\"isId\":false,\"isReadOnly\":false,\"hasDefaultValue\":false,\"type\":\"DateTime\",\"isGenerated\":false,\"isUpdatedAt\":true}],\"primaryKey\":null,\"uniqueFields\":[[\"stressfreiEmailId\",\"messageId\",\"folder\"]],\"uniqueIndexes\":[{\"name\":null,\"fields\":[\"stressfreiEmailId\",\"messageId\",\"folder\"]}],\"isGenerated\":false},\"Meter\":{\"dbName\":null,\"fields\":[{\"name\":\"id\",\"kind\":\"scalar\",\"isList\":false,\"isRequired\":true,\"isUnique\":false,\"isId\":true,\"isReadOnly\":false,\"hasDefaultValue\":true,\"type\":\"Int\",\"default\":{\"name\":\"autoincrement\",\"args\":[]},\"isGenerated\":false,\"isUpdatedAt\":false},{\"name\":\"customerId\",\"kind\":\"scalar\",\"isList\":false,\"isRequired\":true,\"isUnique\":false,\"isId\":false,\"isReadOnly\":true,\"hasDefaultValue\":false,\"type\":\"Int\",\"isGenerated\":false,\"isUpdatedAt\":false},{\"name\":\"customer\",\"kind\":\"object\",\"isList\":false,\"isRequired\":true,\"isUnique\":false,\"isId\":false,\"isReadOnly\":false,\"hasDefaultValue\":false,\"type\":\"Customer\",\"relationName\":\"CustomerToMeter\",\"relationFromFields\":[\"customerId\"],\"relationToFields\":[\"id\"],\"relationOnDelete\":\"Cascade\",\"isGenerated\":false,\"isUpdatedAt\":false},{\"name\":\"meterNumber\",\"kind\":\"scalar\",\"isList\":false,\"isRequired\":true,\"isUnique\":false,\"isId\":false,\"isReadOnly\":false,\"hasDefaultValue\":false,\"type\":\"String\",\"isGenerated\":false,\"isUpdatedAt\":false},{\"name\":\"type\",\"kind\":\"enum\",\"isList\":false,\"isRequired\":true,\"isUnique\":false,\"isId\":false,\"isReadOnly\":false,\"hasDefaultValue\":false,\"type\":\"MeterType\",\"isGenerated\":false,\"isUpdatedAt\":false},{\"name\":\"location\",\"kind\":\"scalar\",\"isList\":false,\"isRequired\":false,\"isUnique\":false,\"isId\":false,\"isReadOnly\":false,\"hasDefaultValue\":false,\"type\":\"String\",\"isGenerated\":false,\"isUpdatedAt\":false},{\"name\":\"isActive\",\"kind\":\"scalar\",\"isList\":false,\"isRequired\":true,\"isUnique\":false,\"isId\":false,\"isReadOnly\":false,\"hasDefaultValue\":true,\"type\":\"Boolean\",\"default\":true,\"isGenerated\":false,\"isUpdatedAt\":false},{\"name\":\"readings\",\"kind\":\"object\",\"isList\":true,\"isRequired\":true,\"isUnique\":false,\"isId\":false,\"isReadOnly\":false,\"hasDefaultValue\":false,\"type\":\"MeterReading\",\"relationName\":\"MeterToMeterReading\",\"relationFromFields\":[],\"relationToFields\":[],\"isGenerated\":false,\"isUpdatedAt\":false},{\"name\":\"energyDetails\",\"kind\":\"object\",\"isList\":true,\"isRequired\":true,\"isUnique\":false,\"isId\":false,\"isReadOnly\":false,\"hasDefaultValue\":false,\"type\":\"EnergyContractDetails\",\"relationName\":\"EnergyContractDetailsToMeter\",\"relationFromFields\":[],\"relationToFields\":[],\"isGenerated\":false,\"isUpdatedAt\":false},{\"name\":\"createdAt\",\"kind\":\"scalar\",\"isList\":false,\"isRequired\":true,\"isUnique\":false,\"isId\":false,\"isReadOnly\":false,\"hasDefaultValue\":true,\"type\":\"DateTime\",\"default\":{\"name\":\"now\",\"args\":[]},\"isGenerated\":false,\"isUpdatedAt\":false},{\"name\":\"updatedAt\",\"kind\":\"scalar\",\"isList\":false,\"isRequired\":true,\"isUnique\":false,\"isId\":false,\"isReadOnly\":false,\"hasDefaultValue\":false,\"type\":\"DateTime\",\"isGenerated\":false,\"isUpdatedAt\":true}],\"primaryKey\":null,\"uniqueFields\":[],\"uniqueIndexes\":[],\"isGenerated\":false},\"MeterReading\":{\"dbName\":null,\"fields\":[{\"name\":\"id\",\"kind\":\"scalar\",\"isList\":false,\"isRequired\":true,\"isUnique\":false,\"isId\":true,\"isReadOnly\":false,\"hasDefaultValue\":true,\"type\":\"Int\",\"default\":{\"name\":\"autoincrement\",\"args\":[]},\"isGenerated\":false,\"isUpdatedAt\":false},{\"name\":\"meterId\",\"kind\":\"scalar\",\"isList\":false,\"isRequired\":true,\"isUnique\":false,\"isId\":false,\"isReadOnly\":true,\"hasDefaultValue\":false,\"type\":\"Int\",\"isGenerated\":false,\"isUpdatedAt\":false},{\"name\":\"meter\",\"kind\":\"object\",\"isList\":false,\"isRequired\":true,\"isUnique\":false,\"isId\":false,\"isReadOnly\":false,\"hasDefaultValue\":false,\"type\":\"Meter\",\"relationName\":\"MeterToMeterReading\",\"relationFromFields\":[\"meterId\"],\"relationToFields\":[\"id\"],\"relationOnDelete\":\"Cascade\",\"isGenerated\":false,\"isUpdatedAt\":false},{\"name\":\"readingDate\",\"kind\":\"scalar\",\"isList\":false,\"isRequired\":true,\"isUnique\":false,\"isId\":false,\"isReadOnly\":false,\"hasDefaultValue\":false,\"type\":\"DateTime\",\"isGenerated\":false,\"isUpdatedAt\":false},{\"name\":\"value\",\"kind\":\"scalar\",\"isList\":false,\"isRequired\":true,\"isUnique\":false,\"isId\":false,\"isReadOnly\":false,\"hasDefaultValue\":false,\"type\":\"Float\",\"isGenerated\":false,\"isUpdatedAt\":false},{\"name\":\"unit\",\"kind\":\"scalar\",\"isList\":false,\"isRequired\":true,\"isUnique\":false,\"isId\":false,\"isReadOnly\":false,\"hasDefaultValue\":true,\"type\":\"String\",\"default\":\"kWh\",\"isGenerated\":false,\"isUpdatedAt\":false},{\"name\":\"notes\",\"kind\":\"scalar\",\"isList\":false,\"isRequired\":false,\"isUnique\":false,\"isId\":false,\"isReadOnly\":false,\"hasDefaultValue\":false,\"type\":\"String\",\"isGenerated\":false,\"isUpdatedAt\":false},{\"name\":\"createdAt\",\"kind\":\"scalar\",\"isList\":false,\"isRequired\":true,\"isUnique\":false,\"isId\":false,\"isReadOnly\":false,\"hasDefaultValue\":true,\"type\":\"DateTime\",\"default\":{\"name\":\"now\",\"args\":[]},\"isGenerated\":false,\"isUpdatedAt\":false}],\"primaryKey\":null,\"uniqueFields\":[],\"uniqueIndexes\":[],\"isGenerated\":false},\"SalesPlatform\":{\"dbName\":null,\"fields\":[{\"name\":\"id\",\"kind\":\"scalar\",\"isList\":false,\"isRequired\":true,\"isUnique\":false,\"isId\":true,\"isReadOnly\":false,\"hasDefaultValue\":true,\"type\":\"Int\",\"default\":{\"name\":\"autoincrement\",\"args\":[]},\"isGenerated\":false,\"isUpdatedAt\":false},{\"name\":\"name\",\"kind\":\"scalar\",\"isList\":false,\"isRequired\":true,\"isUnique\":true,\"isId\":false,\"isReadOnly\":false,\"hasDefaultValue\":false,\"type\":\"String\",\"isGenerated\":false,\"isUpdatedAt\":false},{\"name\":\"contactInfo\",\"kind\":\"scalar\",\"isList\":false,\"isRequired\":false,\"isUnique\":false,\"isId\":false,\"isReadOnly\":false,\"hasDefaultValue\":false,\"type\":\"String\",\"isGenerated\":false,\"isUpdatedAt\":false},{\"name\":\"isActive\",\"kind\":\"scalar\",\"isList\":false,\"isRequired\":true,\"isUnique\":false,\"isId\":false,\"isReadOnly\":false,\"hasDefaultValue\":true,\"type\":\"Boolean\",\"default\":true,\"isGenerated\":false,\"isUpdatedAt\":false},{\"name\":\"contracts\",\"kind\":\"object\",\"isList\":true,\"isRequired\":true,\"isUnique\":false,\"isId\":false,\"isReadOnly\":false,\"hasDefaultValue\":false,\"type\":\"Contract\",\"relationName\":\"ContractToSalesPlatform\",\"relationFromFields\":[],\"relationToFields\":[],\"isGenerated\":false,\"isUpdatedAt\":false},{\"name\":\"createdAt\",\"kind\":\"scalar\",\"isList\":false,\"isRequired\":true,\"isUnique\":false,\"isId\":false,\"isReadOnly\":false,\"hasDefaultValue\":true,\"type\":\"DateTime\",\"default\":{\"name\":\"now\",\"args\":[]},\"isGenerated\":false,\"isUpdatedAt\":false},{\"name\":\"updatedAt\",\"kind\":\"scalar\",\"isList\":false,\"isRequired\":true,\"isUnique\":false,\"isId\":false,\"isReadOnly\":false,\"hasDefaultValue\":false,\"type\":\"DateTime\",\"isGenerated\":false,\"isUpdatedAt\":true}],\"primaryKey\":null,\"uniqueFields\":[],\"uniqueIndexes\":[],\"isGenerated\":false},\"CancellationPeriod\":{\"dbName\":null,\"fields\":[{\"name\":\"id\",\"kind\":\"scalar\",\"isList\":false,\"isRequired\":true,\"isUnique\":false,\"isId\":true,\"isReadOnly\":false,\"hasDefaultValue\":true,\"type\":\"Int\",\"default\":{\"name\":\"autoincrement\",\"args\":[]},\"isGenerated\":false,\"isUpdatedAt\":false},{\"name\":\"code\",\"kind\":\"scalar\",\"isList\":false,\"isRequired\":true,\"isUnique\":true,\"isId\":false,\"isReadOnly\":false,\"hasDefaultValue\":false,\"type\":\"String\",\"isGenerated\":false,\"isUpdatedAt\":false},{\"name\":\"description\",\"kind\":\"scalar\",\"isList\":false,\"isRequired\":true,\"isUnique\":false,\"isId\":false,\"isReadOnly\":false,\"hasDefaultValue\":false,\"type\":\"String\",\"isGenerated\":false,\"isUpdatedAt\":false},{\"name\":\"isActive\",\"kind\":\"scalar\",\"isList\":false,\"isRequired\":true,\"isUnique\":false,\"isId\":false,\"isReadOnly\":false,\"hasDefaultValue\":true,\"type\":\"Boolean\",\"default\":true,\"isGenerated\":false,\"isUpdatedAt\":false},{\"name\":\"contracts\",\"kind\":\"object\",\"isList\":true,\"isRequired\":true,\"isUnique\":false,\"isId\":false,\"isReadOnly\":false,\"hasDefaultValue\":false,\"type\":\"Contract\",\"relationName\":\"CancellationPeriodToContract\",\"relationFromFields\":[],\"relationToFields\":[],\"isGenerated\":false,\"isUpdatedAt\":false},{\"name\":\"createdAt\",\"kind\":\"scalar\",\"isList\":false,\"isRequired\":true,\"isUnique\":false,\"isId\":false,\"isReadOnly\":false,\"hasDefaultValue\":true,\"type\":\"DateTime\",\"default\":{\"name\":\"now\",\"args\":[]},\"isGenerated\":false,\"isUpdatedAt\":false},{\"name\":\"updatedAt\",\"kind\":\"scalar\",\"isList\":false,\"isRequired\":true,\"isUnique\":false,\"isId\":false,\"isReadOnly\":false,\"hasDefaultValue\":false,\"type\":\"DateTime\",\"isGenerated\":false,\"isUpdatedAt\":true}],\"primaryKey\":null,\"uniqueFields\":[],\"uniqueIndexes\":[],\"isGenerated\":false},\"ContractDuration\":{\"dbName\":null,\"fields\":[{\"name\":\"id\",\"kind\":\"scalar\",\"isList\":false,\"isRequired\":true,\"isUnique\":false,\"isId\":true,\"isReadOnly\":false,\"hasDefaultValue\":true,\"type\":\"Int\",\"default\":{\"name\":\"autoincrement\",\"args\":[]},\"isGenerated\":false,\"isUpdatedAt\":false},{\"name\":\"code\",\"kind\":\"scalar\",\"isList\":false,\"isRequired\":true,\"isUnique\":true,\"isId\":false,\"isReadOnly\":false,\"hasDefaultValue\":false,\"type\":\"String\",\"isGenerated\":false,\"isUpdatedAt\":false},{\"name\":\"description\",\"kind\":\"scalar\",\"isList\":false,\"isRequired\":true,\"isUnique\":false,\"isId\":false,\"isReadOnly\":false,\"hasDefaultValue\":false,\"type\":\"String\",\"isGenerated\":false,\"isUpdatedAt\":false},{\"name\":\"isActive\",\"kind\":\"scalar\",\"isList\":false,\"isRequired\":true,\"isUnique\":false,\"isId\":false,\"isReadOnly\":false,\"hasDefaultValue\":true,\"type\":\"Boolean\",\"default\":true,\"isGenerated\":false,\"isUpdatedAt\":false},{\"name\":\"contracts\",\"kind\":\"object\",\"isList\":true,\"isRequired\":true,\"isUnique\":false,\"isId\":false,\"isReadOnly\":false,\"hasDefaultValue\":false,\"type\":\"Contract\",\"relationName\":\"ContractToContractDuration\",\"relationFromFields\":[],\"relationToFields\":[],\"isGenerated\":false,\"isUpdatedAt\":false},{\"name\":\"createdAt\",\"kind\":\"scalar\",\"isList\":false,\"isRequired\":true,\"isUnique\":false,\"isId\":false,\"isReadOnly\":false,\"hasDefaultValue\":true,\"type\":\"DateTime\",\"default\":{\"name\":\"now\",\"args\":[]},\"isGenerated\":false,\"isUpdatedAt\":false},{\"name\":\"updatedAt\",\"kind\":\"scalar\",\"isList\":false,\"isRequired\":true,\"isUnique\":false,\"isId\":false,\"isReadOnly\":false,\"hasDefaultValue\":false,\"type\":\"DateTime\",\"isGenerated\":false,\"isUpdatedAt\":true}],\"primaryKey\":null,\"uniqueFields\":[],\"uniqueIndexes\":[],\"isGenerated\":false},\"Provider\":{\"dbName\":null,\"fields\":[{\"name\":\"id\",\"kind\":\"scalar\",\"isList\":false,\"isRequired\":true,\"isUnique\":false,\"isId\":true,\"isReadOnly\":false,\"hasDefaultValue\":true,\"type\":\"Int\",\"default\":{\"name\":\"autoincrement\",\"args\":[]},\"isGenerated\":false,\"isUpdatedAt\":false},{\"name\":\"name\",\"kind\":\"scalar\",\"isList\":false,\"isRequired\":true,\"isUnique\":true,\"isId\":false,\"isReadOnly\":false,\"hasDefaultValue\":false,\"type\":\"String\",\"isGenerated\":false,\"isUpdatedAt\":false},{\"name\":\"portalUrl\",\"kind\":\"scalar\",\"isList\":false,\"isRequired\":false,\"isUnique\":false,\"isId\":false,\"isReadOnly\":false,\"hasDefaultValue\":false,\"type\":\"String\",\"isGenerated\":false,\"isUpdatedAt\":false},{\"name\":\"usernameFieldName\",\"kind\":\"scalar\",\"isList\":false,\"isRequired\":false,\"isUnique\":false,\"isId\":false,\"isReadOnly\":false,\"hasDefaultValue\":false,\"type\":\"String\",\"isGenerated\":false,\"isUpdatedAt\":false},{\"name\":\"passwordFieldName\",\"kind\":\"scalar\",\"isList\":false,\"isRequired\":false,\"isUnique\":false,\"isId\":false,\"isReadOnly\":false,\"hasDefaultValue\":false,\"type\":\"String\",\"isGenerated\":false,\"isUpdatedAt\":false},{\"name\":\"isActive\",\"kind\":\"scalar\",\"isList\":false,\"isRequired\":true,\"isUnique\":false,\"isId\":false,\"isReadOnly\":false,\"hasDefaultValue\":true,\"type\":\"Boolean\",\"default\":true,\"isGenerated\":false,\"isUpdatedAt\":false},{\"name\":\"tariffs\",\"kind\":\"object\",\"isList\":true,\"isRequired\":true,\"isUnique\":false,\"isId\":false,\"isReadOnly\":false,\"hasDefaultValue\":false,\"type\":\"Tariff\",\"relationName\":\"ProviderToTariff\",\"relationFromFields\":[],\"relationToFields\":[],\"isGenerated\":false,\"isUpdatedAt\":false},{\"name\":\"contracts\",\"kind\":\"object\",\"isList\":true,\"isRequired\":true,\"isUnique\":false,\"isId\":false,\"isReadOnly\":false,\"hasDefaultValue\":false,\"type\":\"Contract\",\"relationName\":\"ContractToProvider\",\"relationFromFields\":[],\"relationToFields\":[],\"isGenerated\":false,\"isUpdatedAt\":false},{\"name\":\"createdAt\",\"kind\":\"scalar\",\"isList\":false,\"isRequired\":true,\"isUnique\":false,\"isId\":false,\"isReadOnly\":false,\"hasDefaultValue\":true,\"type\":\"DateTime\",\"default\":{\"name\":\"now\",\"args\":[]},\"isGenerated\":false,\"isUpdatedAt\":false},{\"name\":\"updatedAt\",\"kind\":\"scalar\",\"isList\":false,\"isRequired\":true,\"isUnique\":false,\"isId\":false,\"isReadOnly\":false,\"hasDefaultValue\":false,\"type\":\"DateTime\",\"isGenerated\":false,\"isUpdatedAt\":true}],\"primaryKey\":null,\"uniqueFields\":[],\"uniqueIndexes\":[],\"isGenerated\":false},\"Tariff\":{\"dbName\":null,\"fields\":[{\"name\":\"id\",\"kind\":\"scalar\",\"isList\":false,\"isRequired\":true,\"isUnique\":false,\"isId\":true,\"isReadOnly\":false,\"hasDefaultValue\":true,\"type\":\"Int\",\"default\":{\"name\":\"autoincrement\",\"args\":[]},\"isGenerated\":false,\"isUpdatedAt\":false},{\"name\":\"providerId\",\"kind\":\"scalar\",\"isList\":false,\"isRequired\":true,\"isUnique\":false,\"isId\":false,\"isReadOnly\":true,\"hasDefaultValue\":false,\"type\":\"Int\",\"isGenerated\":false,\"isUpdatedAt\":false},{\"name\":\"provider\",\"kind\":\"object\",\"isList\":false,\"isRequired\":true,\"isUnique\":false,\"isId\":false,\"isReadOnly\":false,\"hasDefaultValue\":false,\"type\":\"Provider\",\"relationName\":\"ProviderToTariff\",\"relationFromFields\":[\"providerId\"],\"relationToFields\":[\"id\"],\"relationOnDelete\":\"Cascade\",\"isGenerated\":false,\"isUpdatedAt\":false},{\"name\":\"name\",\"kind\":\"scalar\",\"isList\":false,\"isRequired\":true,\"isUnique\":false,\"isId\":false,\"isReadOnly\":false,\"hasDefaultValue\":false,\"type\":\"String\",\"isGenerated\":false,\"isUpdatedAt\":false},{\"name\":\"isActive\",\"kind\":\"scalar\",\"isList\":false,\"isRequired\":true,\"isUnique\":false,\"isId\":false,\"isReadOnly\":false,\"hasDefaultValue\":true,\"type\":\"Boolean\",\"default\":true,\"isGenerated\":false,\"isUpdatedAt\":false},{\"name\":\"contracts\",\"kind\":\"object\",\"isList\":true,\"isRequired\":true,\"isUnique\":false,\"isId\":false,\"isReadOnly\":false,\"hasDefaultValue\":false,\"type\":\"Contract\",\"relationName\":\"ContractToTariff\",\"relationFromFields\":[],\"relationToFields\":[],\"isGenerated\":false,\"isUpdatedAt\":false},{\"name\":\"createdAt\",\"kind\":\"scalar\",\"isList\":false,\"isRequired\":true,\"isUnique\":false,\"isId\":false,\"isReadOnly\":false,\"hasDefaultValue\":true,\"type\":\"DateTime\",\"default\":{\"name\":\"now\",\"args\":[]},\"isGenerated\":false,\"isUpdatedAt\":false},{\"name\":\"updatedAt\",\"kind\":\"scalar\",\"isList\":false,\"isRequired\":true,\"isUnique\":false,\"isId\":false,\"isReadOnly\":false,\"hasDefaultValue\":false,\"type\":\"DateTime\",\"isGenerated\":false,\"isUpdatedAt\":true}],\"primaryKey\":null,\"uniqueFields\":[[\"providerId\",\"name\"]],\"uniqueIndexes\":[{\"name\":null,\"fields\":[\"providerId\",\"name\"]}],\"isGenerated\":false},\"ContractCategory\":{\"dbName\":null,\"fields\":[{\"name\":\"id\",\"kind\":\"scalar\",\"isList\":false,\"isRequired\":true,\"isUnique\":false,\"isId\":true,\"isReadOnly\":false,\"hasDefaultValue\":true,\"type\":\"Int\",\"default\":{\"name\":\"autoincrement\",\"args\":[]},\"isGenerated\":false,\"isUpdatedAt\":false},{\"name\":\"code\",\"kind\":\"scalar\",\"isList\":false,\"isRequired\":true,\"isUnique\":true,\"isId\":false,\"isReadOnly\":false,\"hasDefaultValue\":false,\"type\":\"String\",\"isGenerated\":false,\"isUpdatedAt\":false},{\"name\":\"name\",\"kind\":\"scalar\",\"isList\":false,\"isRequired\":true,\"isUnique\":false,\"isId\":false,\"isReadOnly\":false,\"hasDefaultValue\":false,\"type\":\"String\",\"isGenerated\":false,\"isUpdatedAt\":false},{\"name\":\"icon\",\"kind\":\"scalar\",\"isList\":false,\"isRequired\":false,\"isUnique\":false,\"isId\":false,\"isReadOnly\":false,\"hasDefaultValue\":false,\"type\":\"String\",\"isGenerated\":false,\"isUpdatedAt\":false},{\"name\":\"color\",\"kind\":\"scalar\",\"isList\":false,\"isRequired\":false,\"isUnique\":false,\"isId\":false,\"isReadOnly\":false,\"hasDefaultValue\":false,\"type\":\"String\",\"isGenerated\":false,\"isUpdatedAt\":false},{\"name\":\"sortOrder\",\"kind\":\"scalar\",\"isList\":false,\"isRequired\":true,\"isUnique\":false,\"isId\":false,\"isReadOnly\":false,\"hasDefaultValue\":true,\"type\":\"Int\",\"default\":0,\"isGenerated\":false,\"isUpdatedAt\":false},{\"name\":\"isActive\",\"kind\":\"scalar\",\"isList\":false,\"isRequired\":true,\"isUnique\":false,\"isId\":false,\"isReadOnly\":false,\"hasDefaultValue\":true,\"type\":\"Boolean\",\"default\":true,\"isGenerated\":false,\"isUpdatedAt\":false},{\"name\":\"contracts\",\"kind\":\"object\",\"isList\":true,\"isRequired\":true,\"isUnique\":false,\"isId\":false,\"isReadOnly\":false,\"hasDefaultValue\":false,\"type\":\"Contract\",\"relationName\":\"ContractToContractCategory\",\"relationFromFields\":[],\"relationToFields\":[],\"isGenerated\":false,\"isUpdatedAt\":false},{\"name\":\"createdAt\",\"kind\":\"scalar\",\"isList\":false,\"isRequired\":true,\"isUnique\":false,\"isId\":false,\"isReadOnly\":false,\"hasDefaultValue\":true,\"type\":\"DateTime\",\"default\":{\"name\":\"now\",\"args\":[]},\"isGenerated\":false,\"isUpdatedAt\":false},{\"name\":\"updatedAt\",\"kind\":\"scalar\",\"isList\":false,\"isRequired\":true,\"isUnique\":false,\"isId\":false,\"isReadOnly\":false,\"hasDefaultValue\":false,\"type\":\"DateTime\",\"isGenerated\":false,\"isUpdatedAt\":true}],\"primaryKey\":null,\"uniqueFields\":[],\"uniqueIndexes\":[],\"isGenerated\":false},\"Contract\":{\"dbName\":null,\"fields\":[{\"name\":\"id\",\"kind\":\"scalar\",\"isList\":false,\"isRequired\":true,\"isUnique\":false,\"isId\":true,\"isReadOnly\":false,\"hasDefaultValue\":true,\"type\":\"Int\",\"default\":{\"name\":\"autoincrement\",\"args\":[]},\"isGenerated\":false,\"isUpdatedAt\":false},{\"name\":\"contractNumber\",\"kind\":\"scalar\",\"isList\":false,\"isRequired\":true,\"isUnique\":true,\"isId\":false,\"isReadOnly\":false,\"hasDefaultValue\":false,\"type\":\"String\",\"isGenerated\":false,\"isUpdatedAt\":false},{\"name\":\"customerId\",\"kind\":\"scalar\",\"isList\":false,\"isRequired\":true,\"isUnique\":false,\"isId\":false,\"isReadOnly\":true,\"hasDefaultValue\":false,\"type\":\"Int\",\"isGenerated\":false,\"isUpdatedAt\":false},{\"name\":\"customer\",\"kind\":\"object\",\"isList\":false,\"isRequired\":true,\"isUnique\":false,\"isId\":false,\"isReadOnly\":false,\"hasDefaultValue\":false,\"type\":\"Customer\",\"relationName\":\"ContractToCustomer\",\"relationFromFields\":[\"customerId\"],\"relationToFields\":[\"id\"],\"relationOnDelete\":\"Cascade\",\"isGenerated\":false,\"isUpdatedAt\":false},{\"name\":\"type\",\"kind\":\"enum\",\"isList\":false,\"isRequired\":true,\"isUnique\":false,\"isId\":false,\"isReadOnly\":false,\"hasDefaultValue\":false,\"type\":\"ContractType\",\"isGenerated\":false,\"isUpdatedAt\":false},{\"name\":\"status\",\"kind\":\"enum\",\"isList\":false,\"isRequired\":true,\"isUnique\":false,\"isId\":false,\"isReadOnly\":false,\"hasDefaultValue\":true,\"type\":\"ContractStatus\",\"default\":\"DRAFT\",\"isGenerated\":false,\"isUpdatedAt\":false},{\"name\":\"contractCategoryId\",\"kind\":\"scalar\",\"isList\":false,\"isRequired\":false,\"isUnique\":false,\"isId\":false,\"isReadOnly\":true,\"hasDefaultValue\":false,\"type\":\"Int\",\"isGenerated\":false,\"isUpdatedAt\":false},{\"name\":\"contractCategory\",\"kind\":\"object\",\"isList\":false,\"isRequired\":false,\"isUnique\":false,\"isId\":false,\"isReadOnly\":false,\"hasDefaultValue\":false,\"type\":\"ContractCategory\",\"relationName\":\"ContractToContractCategory\",\"relationFromFields\":[\"contractCategoryId\"],\"relationToFields\":[\"id\"],\"isGenerated\":false,\"isUpdatedAt\":false},{\"name\":\"addressId\",\"kind\":\"scalar\",\"isList\":false,\"isRequired\":false,\"isUnique\":false,\"isId\":false,\"isReadOnly\":true,\"hasDefaultValue\":false,\"type\":\"Int\",\"isGenerated\":false,\"isUpdatedAt\":false},{\"name\":\"address\",\"kind\":\"object\",\"isList\":false,\"isRequired\":false,\"isUnique\":false,\"isId\":false,\"isReadOnly\":false,\"hasDefaultValue\":false,\"type\":\"Address\",\"relationName\":\"AddressToContract\",\"relationFromFields\":[\"addressId\"],\"relationToFields\":[\"id\"],\"isGenerated\":false,\"isUpdatedAt\":false},{\"name\":\"bankCardId\",\"kind\":\"scalar\",\"isList\":false,\"isRequired\":false,\"isUnique\":false,\"isId\":false,\"isReadOnly\":true,\"hasDefaultValue\":false,\"type\":\"Int\",\"isGenerated\":false,\"isUpdatedAt\":false},{\"name\":\"bankCard\",\"kind\":\"object\",\"isList\":false,\"isRequired\":false,\"isUnique\":false,\"isId\":false,\"isReadOnly\":false,\"hasDefaultValue\":false,\"type\":\"BankCard\",\"relationName\":\"BankCardToContract\",\"relationFromFields\":[\"bankCardId\"],\"relationToFields\":[\"id\"],\"isGenerated\":false,\"isUpdatedAt\":false},{\"name\":\"identityDocumentId\",\"kind\":\"scalar\",\"isList\":false,\"isRequired\":false,\"isUnique\":false,\"isId\":false,\"isReadOnly\":true,\"hasDefaultValue\":false,\"type\":\"Int\",\"isGenerated\":false,\"isUpdatedAt\":false},{\"name\":\"identityDocument\",\"kind\":\"object\",\"isList\":false,\"isRequired\":false,\"isUnique\":false,\"isId\":false,\"isReadOnly\":false,\"hasDefaultValue\":false,\"type\":\"IdentityDocument\",\"relationName\":\"ContractToIdentityDocument\",\"relationFromFields\":[\"identityDocumentId\"],\"relationToFields\":[\"id\"],\"isGenerated\":false,\"isUpdatedAt\":false},{\"name\":\"salesPlatformId\",\"kind\":\"scalar\",\"isList\":false,\"isRequired\":false,\"isUnique\":false,\"isId\":false,\"isReadOnly\":true,\"hasDefaultValue\":false,\"type\":\"Int\",\"isGenerated\":false,\"isUpdatedAt\":false},{\"name\":\"salesPlatform\",\"kind\":\"object\",\"isList\":false,\"isRequired\":false,\"isUnique\":false,\"isId\":false,\"isReadOnly\":false,\"hasDefaultValue\":false,\"type\":\"SalesPlatform\",\"relationName\":\"ContractToSalesPlatform\",\"relationFromFields\":[\"salesPlatformId\"],\"relationToFields\":[\"id\"],\"isGenerated\":false,\"isUpdatedAt\":false},{\"name\":\"cancellationPeriodId\",\"kind\":\"scalar\",\"isList\":false,\"isRequired\":false,\"isUnique\":false,\"isId\":false,\"isReadOnly\":true,\"hasDefaultValue\":false,\"type\":\"Int\",\"isGenerated\":false,\"isUpdatedAt\":false},{\"name\":\"cancellationPeriod\",\"kind\":\"object\",\"isList\":false,\"isRequired\":false,\"isUnique\":false,\"isId\":false,\"isReadOnly\":false,\"hasDefaultValue\":false,\"type\":\"CancellationPeriod\",\"relationName\":\"CancellationPeriodToContract\",\"relationFromFields\":[\"cancellationPeriodId\"],\"relationToFields\":[\"id\"],\"isGenerated\":false,\"isUpdatedAt\":false},{\"name\":\"contractDurationId\",\"kind\":\"scalar\",\"isList\":false,\"isRequired\":false,\"isUnique\":false,\"isId\":false,\"isReadOnly\":true,\"hasDefaultValue\":false,\"type\":\"Int\",\"isGenerated\":false,\"isUpdatedAt\":false},{\"name\":\"contractDuration\",\"kind\":\"object\",\"isList\":false,\"isRequired\":false,\"isUnique\":false,\"isId\":false,\"isReadOnly\":false,\"hasDefaultValue\":false,\"type\":\"ContractDuration\",\"relationName\":\"ContractToContractDuration\",\"relationFromFields\":[\"contractDurationId\"],\"relationToFields\":[\"id\"],\"isGenerated\":false,\"isUpdatedAt\":false},{\"name\":\"previousContractId\",\"kind\":\"scalar\",\"isList\":false,\"isRequired\":false,\"isUnique\":true,\"isId\":false,\"isReadOnly\":true,\"hasDefaultValue\":false,\"type\":\"Int\",\"isGenerated\":false,\"isUpdatedAt\":false},{\"name\":\"previousContract\",\"kind\":\"object\",\"isList\":false,\"isRequired\":false,\"isUnique\":false,\"isId\":false,\"isReadOnly\":false,\"hasDefaultValue\":false,\"type\":\"Contract\",\"relationName\":\"ContractHistory\",\"relationFromFields\":[\"previousContractId\"],\"relationToFields\":[\"id\"],\"isGenerated\":false,\"isUpdatedAt\":false},{\"name\":\"followUpContract\",\"kind\":\"object\",\"isList\":false,\"isRequired\":false,\"isUnique\":false,\"isId\":false,\"isReadOnly\":false,\"hasDefaultValue\":false,\"type\":\"Contract\",\"relationName\":\"ContractHistory\",\"relationFromFields\":[],\"relationToFields\":[],\"isGenerated\":false,\"isUpdatedAt\":false},{\"name\":\"providerId\",\"kind\":\"scalar\",\"isList\":false,\"isRequired\":false,\"isUnique\":false,\"isId\":false,\"isReadOnly\":true,\"hasDefaultValue\":false,\"type\":\"Int\",\"isGenerated\":false,\"isUpdatedAt\":false},{\"name\":\"provider\",\"kind\":\"object\",\"isList\":false,\"isRequired\":false,\"isUnique\":false,\"isId\":false,\"isReadOnly\":false,\"hasDefaultValue\":false,\"type\":\"Provider\",\"relationName\":\"ContractToProvider\",\"relationFromFields\":[\"providerId\"],\"relationToFields\":[\"id\"],\"isGenerated\":false,\"isUpdatedAt\":false},{\"name\":\"tariffId\",\"kind\":\"scalar\",\"isList\":false,\"isRequired\":false,\"isUnique\":false,\"isId\":false,\"isReadOnly\":true,\"hasDefaultValue\":false,\"type\":\"Int\",\"isGenerated\":false,\"isUpdatedAt\":false},{\"name\":\"tariff\",\"kind\":\"object\",\"isList\":false,\"isRequired\":false,\"isUnique\":false,\"isId\":false,\"isReadOnly\":false,\"hasDefaultValue\":false,\"type\":\"Tariff\",\"relationName\":\"ContractToTariff\",\"relationFromFields\":[\"tariffId\"],\"relationToFields\":[\"id\"],\"isGenerated\":false,\"isUpdatedAt\":false},{\"name\":\"providerName\",\"kind\":\"scalar\",\"isList\":false,\"isRequired\":false,\"isUnique\":false,\"isId\":false,\"isReadOnly\":false,\"hasDefaultValue\":false,\"type\":\"String\",\"isGenerated\":false,\"isUpdatedAt\":false},{\"name\":\"tariffName\",\"kind\":\"scalar\",\"isList\":false,\"isRequired\":false,\"isUnique\":false,\"isId\":false,\"isReadOnly\":false,\"hasDefaultValue\":false,\"type\":\"String\",\"isGenerated\":false,\"isUpdatedAt\":false},{\"name\":\"customerNumberAtProvider\",\"kind\":\"scalar\",\"isList\":false,\"isRequired\":false,\"isUnique\":false,\"isId\":false,\"isReadOnly\":false,\"hasDefaultValue\":false,\"type\":\"String\",\"isGenerated\":false,\"isUpdatedAt\":false},{\"name\":\"priceFirst12Months\",\"kind\":\"scalar\",\"isList\":false,\"isRequired\":false,\"isUnique\":false,\"isId\":false,\"isReadOnly\":false,\"hasDefaultValue\":false,\"type\":\"String\",\"isGenerated\":false,\"isUpdatedAt\":false},{\"name\":\"priceFrom13Months\",\"kind\":\"scalar\",\"isList\":false,\"isRequired\":false,\"isUnique\":false,\"isId\":false,\"isReadOnly\":false,\"hasDefaultValue\":false,\"type\":\"String\",\"isGenerated\":false,\"isUpdatedAt\":false},{\"name\":\"priceAfter24Months\",\"kind\":\"scalar\",\"isList\":false,\"isRequired\":false,\"isUnique\":false,\"isId\":false,\"isReadOnly\":false,\"hasDefaultValue\":false,\"type\":\"String\",\"isGenerated\":false,\"isUpdatedAt\":false},{\"name\":\"startDate\",\"kind\":\"scalar\",\"isList\":false,\"isRequired\":false,\"isUnique\":false,\"isId\":false,\"isReadOnly\":false,\"hasDefaultValue\":false,\"type\":\"DateTime\",\"isGenerated\":false,\"isUpdatedAt\":false},{\"name\":\"endDate\",\"kind\":\"scalar\",\"isList\":false,\"isRequired\":false,\"isUnique\":false,\"isId\":false,\"isReadOnly\":false,\"hasDefaultValue\":false,\"type\":\"DateTime\",\"isGenerated\":false,\"isUpdatedAt\":false},{\"name\":\"commission\",\"kind\":\"scalar\",\"isList\":false,\"isRequired\":false,\"isUnique\":false,\"isId\":false,\"isReadOnly\":false,\"hasDefaultValue\":false,\"type\":\"Float\",\"isGenerated\":false,\"isUpdatedAt\":false},{\"name\":\"cancellationLetterPath\",\"kind\":\"scalar\",\"isList\":false,\"isRequired\":false,\"isUnique\":false,\"isId\":false,\"isReadOnly\":false,\"hasDefaultValue\":false,\"type\":\"String\",\"isGenerated\":false,\"isUpdatedAt\":false},{\"name\":\"cancellationConfirmationPath\",\"kind\":\"scalar\",\"isList\":false,\"isRequired\":false,\"isUnique\":false,\"isId\":false,\"isReadOnly\":false,\"hasDefaultValue\":false,\"type\":\"String\",\"isGenerated\":false,\"isUpdatedAt\":false},{\"name\":\"cancellationLetterOptionsPath\",\"kind\":\"scalar\",\"isList\":false,\"isRequired\":false,\"isUnique\":false,\"isId\":false,\"isReadOnly\":false,\"hasDefaultValue\":false,\"type\":\"String\",\"isGenerated\":false,\"isUpdatedAt\":false},{\"name\":\"cancellationConfirmationOptionsPath\",\"kind\":\"scalar\",\"isList\":false,\"isRequired\":false,\"isUnique\":false,\"isId\":false,\"isReadOnly\":false,\"hasDefaultValue\":false,\"type\":\"String\",\"isGenerated\":false,\"isUpdatedAt\":false},{\"name\":\"cancellationConfirmationDate\",\"kind\":\"scalar\",\"isList\":false,\"isRequired\":false,\"isUnique\":false,\"isId\":false,\"isReadOnly\":false,\"hasDefaultValue\":false,\"type\":\"DateTime\",\"isGenerated\":false,\"isUpdatedAt\":false},{\"name\":\"cancellationConfirmationOptionsDate\",\"kind\":\"scalar\",\"isList\":false,\"isRequired\":false,\"isUnique\":false,\"isId\":false,\"isReadOnly\":false,\"hasDefaultValue\":false,\"type\":\"DateTime\",\"isGenerated\":false,\"isUpdatedAt\":false},{\"name\":\"wasSpecialCancellation\",\"kind\":\"scalar\",\"isList\":false,\"isRequired\":true,\"isUnique\":false,\"isId\":false,\"isReadOnly\":false,\"hasDefaultValue\":true,\"type\":\"Boolean\",\"default\":false,\"isGenerated\":false,\"isUpdatedAt\":false},{\"name\":\"portalUsername\",\"kind\":\"scalar\",\"isList\":false,\"isRequired\":false,\"isUnique\":false,\"isId\":false,\"isReadOnly\":false,\"hasDefaultValue\":false,\"type\":\"String\",\"isGenerated\":false,\"isUpdatedAt\":false},{\"name\":\"portalPasswordEncrypted\",\"kind\":\"scalar\",\"isList\":false,\"isRequired\":false,\"isUnique\":false,\"isId\":false,\"isReadOnly\":false,\"hasDefaultValue\":false,\"type\":\"String\",\"isGenerated\":false,\"isUpdatedAt\":false},{\"name\":\"stressfreiEmailId\",\"kind\":\"scalar\",\"isList\":false,\"isRequired\":false,\"isUnique\":false,\"isId\":false,\"isReadOnly\":true,\"hasDefaultValue\":false,\"type\":\"Int\",\"isGenerated\":false,\"isUpdatedAt\":false},{\"name\":\"stressfreiEmail\",\"kind\":\"object\",\"isList\":false,\"isRequired\":false,\"isUnique\":false,\"isId\":false,\"isReadOnly\":false,\"hasDefaultValue\":false,\"type\":\"StressfreiEmail\",\"relationName\":\"ContractToStressfreiEmail\",\"relationFromFields\":[\"stressfreiEmailId\"],\"relationToFields\":[\"id\"],\"isGenerated\":false,\"isUpdatedAt\":false},{\"name\":\"notes\",\"kind\":\"scalar\",\"isList\":false,\"isRequired\":false,\"isUnique\":false,\"isId\":false,\"isReadOnly\":false,\"hasDefaultValue\":false,\"type\":\"String\",\"isGenerated\":false,\"isUpdatedAt\":false},{\"name\":\"energyDetails\",\"kind\":\"object\",\"isList\":false,\"isRequired\":false,\"isUnique\":false,\"isId\":false,\"isReadOnly\":false,\"hasDefaultValue\":false,\"type\":\"EnergyContractDetails\",\"relationName\":\"ContractToEnergyContractDetails\",\"relationFromFields\":[],\"relationToFields\":[],\"isGenerated\":false,\"isUpdatedAt\":false},{\"name\":\"internetDetails\",\"kind\":\"object\",\"isList\":false,\"isRequired\":false,\"isUnique\":false,\"isId\":false,\"isReadOnly\":false,\"hasDefaultValue\":false,\"type\":\"InternetContractDetails\",\"relationName\":\"ContractToInternetContractDetails\",\"relationFromFields\":[],\"relationToFields\":[],\"isGenerated\":false,\"isUpdatedAt\":false},{\"name\":\"mobileDetails\",\"kind\":\"object\",\"isList\":false,\"isRequired\":false,\"isUnique\":false,\"isId\":false,\"isReadOnly\":false,\"hasDefaultValue\":false,\"type\":\"MobileContractDetails\",\"relationName\":\"ContractToMobileContractDetails\",\"relationFromFields\":[],\"relationToFields\":[],\"isGenerated\":false,\"isUpdatedAt\":false},{\"name\":\"tvDetails\",\"kind\":\"object\",\"isList\":false,\"isRequired\":false,\"isUnique\":false,\"isId\":false,\"isReadOnly\":false,\"hasDefaultValue\":false,\"type\":\"TvContractDetails\",\"relationName\":\"ContractToTvContractDetails\",\"relationFromFields\":[],\"relationToFields\":[],\"isGenerated\":false,\"isUpdatedAt\":false},{\"name\":\"carInsuranceDetails\",\"kind\":\"object\",\"isList\":false,\"isRequired\":false,\"isUnique\":false,\"isId\":false,\"isReadOnly\":false,\"hasDefaultValue\":false,\"type\":\"CarInsuranceDetails\",\"relationName\":\"CarInsuranceDetailsToContract\",\"relationFromFields\":[],\"relationToFields\":[],\"isGenerated\":false,\"isUpdatedAt\":false},{\"name\":\"tasks\",\"kind\":\"object\",\"isList\":true,\"isRequired\":true,\"isUnique\":false,\"isId\":false,\"isReadOnly\":false,\"hasDefaultValue\":false,\"type\":\"ContractTask\",\"relationName\":\"ContractToContractTask\",\"relationFromFields\":[],\"relationToFields\":[],\"isGenerated\":false,\"isUpdatedAt\":false},{\"name\":\"assignedEmails\",\"kind\":\"object\",\"isList\":true,\"isRequired\":true,\"isUnique\":false,\"isId\":false,\"isReadOnly\":false,\"hasDefaultValue\":false,\"type\":\"CachedEmail\",\"relationName\":\"CachedEmailToContract\",\"relationFromFields\":[],\"relationToFields\":[],\"isGenerated\":false,\"isUpdatedAt\":false},{\"name\":\"createdAt\",\"kind\":\"scalar\",\"isList\":false,\"isRequired\":true,\"isUnique\":false,\"isId\":false,\"isReadOnly\":false,\"hasDefaultValue\":true,\"type\":\"DateTime\",\"default\":{\"name\":\"now\",\"args\":[]},\"isGenerated\":false,\"isUpdatedAt\":false},{\"name\":\"updatedAt\",\"kind\":\"scalar\",\"isList\":false,\"isRequired\":true,\"isUnique\":false,\"isId\":false,\"isReadOnly\":false,\"hasDefaultValue\":false,\"type\":\"DateTime\",\"isGenerated\":false,\"isUpdatedAt\":true}],\"primaryKey\":null,\"uniqueFields\":[],\"uniqueIndexes\":[],\"isGenerated\":false},\"ContractTask\":{\"dbName\":null,\"fields\":[{\"name\":\"id\",\"kind\":\"scalar\",\"isList\":false,\"isRequired\":true,\"isUnique\":false,\"isId\":true,\"isReadOnly\":false,\"hasDefaultValue\":true,\"type\":\"Int\",\"default\":{\"name\":\"autoincrement\",\"args\":[]},\"isGenerated\":false,\"isUpdatedAt\":false},{\"name\":\"contractId\",\"kind\":\"scalar\",\"isList\":false,\"isRequired\":true,\"isUnique\":false,\"isId\":false,\"isReadOnly\":true,\"hasDefaultValue\":false,\"type\":\"Int\",\"isGenerated\":false,\"isUpdatedAt\":false},{\"name\":\"contract\",\"kind\":\"object\",\"isList\":false,\"isRequired\":true,\"isUnique\":false,\"isId\":false,\"isReadOnly\":false,\"hasDefaultValue\":false,\"type\":\"Contract\",\"relationName\":\"ContractToContractTask\",\"relationFromFields\":[\"contractId\"],\"relationToFields\":[\"id\"],\"relationOnDelete\":\"Cascade\",\"isGenerated\":false,\"isUpdatedAt\":false},{\"name\":\"title\",\"kind\":\"scalar\",\"isList\":false,\"isRequired\":true,\"isUnique\":false,\"isId\":false,\"isReadOnly\":false,\"hasDefaultValue\":false,\"type\":\"String\",\"isGenerated\":false,\"isUpdatedAt\":false},{\"name\":\"description\",\"kind\":\"scalar\",\"isList\":false,\"isRequired\":false,\"isUnique\":false,\"isId\":false,\"isReadOnly\":false,\"hasDefaultValue\":false,\"type\":\"String\",\"isGenerated\":false,\"isUpdatedAt\":false},{\"name\":\"status\",\"kind\":\"enum\",\"isList\":false,\"isRequired\":true,\"isUnique\":false,\"isId\":false,\"isReadOnly\":false,\"hasDefaultValue\":true,\"type\":\"ContractTaskStatus\",\"default\":\"OPEN\",\"isGenerated\":false,\"isUpdatedAt\":false},{\"name\":\"visibleInPortal\",\"kind\":\"scalar\",\"isList\":false,\"isRequired\":true,\"isUnique\":false,\"isId\":false,\"isReadOnly\":false,\"hasDefaultValue\":true,\"type\":\"Boolean\",\"default\":false,\"isGenerated\":false,\"isUpdatedAt\":false},{\"name\":\"createdBy\",\"kind\":\"scalar\",\"isList\":false,\"isRequired\":false,\"isUnique\":false,\"isId\":false,\"isReadOnly\":false,\"hasDefaultValue\":false,\"type\":\"String\",\"isGenerated\":false,\"isUpdatedAt\":false},{\"name\":\"completedAt\",\"kind\":\"scalar\",\"isList\":false,\"isRequired\":false,\"isUnique\":false,\"isId\":false,\"isReadOnly\":false,\"hasDefaultValue\":false,\"type\":\"DateTime\",\"isGenerated\":false,\"isUpdatedAt\":false},{\"name\":\"subtasks\",\"kind\":\"object\",\"isList\":true,\"isRequired\":true,\"isUnique\":false,\"isId\":false,\"isReadOnly\":false,\"hasDefaultValue\":false,\"type\":\"ContractTaskSubtask\",\"relationName\":\"ContractTaskToContractTaskSubtask\",\"relationFromFields\":[],\"relationToFields\":[],\"isGenerated\":false,\"isUpdatedAt\":false},{\"name\":\"createdAt\",\"kind\":\"scalar\",\"isList\":false,\"isRequired\":true,\"isUnique\":false,\"isId\":false,\"isReadOnly\":false,\"hasDefaultValue\":true,\"type\":\"DateTime\",\"default\":{\"name\":\"now\",\"args\":[]},\"isGenerated\":false,\"isUpdatedAt\":false},{\"name\":\"updatedAt\",\"kind\":\"scalar\",\"isList\":false,\"isRequired\":true,\"isUnique\":false,\"isId\":false,\"isReadOnly\":false,\"hasDefaultValue\":false,\"type\":\"DateTime\",\"isGenerated\":false,\"isUpdatedAt\":true}],\"primaryKey\":null,\"uniqueFields\":[],\"uniqueIndexes\":[],\"isGenerated\":false},\"ContractTaskSubtask\":{\"dbName\":null,\"fields\":[{\"name\":\"id\",\"kind\":\"scalar\",\"isList\":false,\"isRequired\":true,\"isUnique\":false,\"isId\":true,\"isReadOnly\":false,\"hasDefaultValue\":true,\"type\":\"Int\",\"default\":{\"name\":\"autoincrement\",\"args\":[]},\"isGenerated\":false,\"isUpdatedAt\":false},{\"name\":\"taskId\",\"kind\":\"scalar\",\"isList\":false,\"isRequired\":true,\"isUnique\":false,\"isId\":false,\"isReadOnly\":true,\"hasDefaultValue\":false,\"type\":\"Int\",\"isGenerated\":false,\"isUpdatedAt\":false},{\"name\":\"task\",\"kind\":\"object\",\"isList\":false,\"isRequired\":true,\"isUnique\":false,\"isId\":false,\"isReadOnly\":false,\"hasDefaultValue\":false,\"type\":\"ContractTask\",\"relationName\":\"ContractTaskToContractTaskSubtask\",\"relationFromFields\":[\"taskId\"],\"relationToFields\":[\"id\"],\"relationOnDelete\":\"Cascade\",\"isGenerated\":false,\"isUpdatedAt\":false},{\"name\":\"title\",\"kind\":\"scalar\",\"isList\":false,\"isRequired\":true,\"isUnique\":false,\"isId\":false,\"isReadOnly\":false,\"hasDefaultValue\":false,\"type\":\"String\",\"isGenerated\":false,\"isUpdatedAt\":false},{\"name\":\"status\",\"kind\":\"enum\",\"isList\":false,\"isRequired\":true,\"isUnique\":false,\"isId\":false,\"isReadOnly\":false,\"hasDefaultValue\":true,\"type\":\"ContractTaskStatus\",\"default\":\"OPEN\",\"isGenerated\":false,\"isUpdatedAt\":false},{\"name\":\"createdBy\",\"kind\":\"scalar\",\"isList\":false,\"isRequired\":false,\"isUnique\":false,\"isId\":false,\"isReadOnly\":false,\"hasDefaultValue\":false,\"type\":\"String\",\"isGenerated\":false,\"isUpdatedAt\":false},{\"name\":\"completedAt\",\"kind\":\"scalar\",\"isList\":false,\"isRequired\":false,\"isUnique\":false,\"isId\":false,\"isReadOnly\":false,\"hasDefaultValue\":false,\"type\":\"DateTime\",\"isGenerated\":false,\"isUpdatedAt\":false},{\"name\":\"createdAt\",\"kind\":\"scalar\",\"isList\":false,\"isRequired\":true,\"isUnique\":false,\"isId\":false,\"isReadOnly\":false,\"hasDefaultValue\":true,\"type\":\"DateTime\",\"default\":{\"name\":\"now\",\"args\":[]},\"isGenerated\":false,\"isUpdatedAt\":false},{\"name\":\"updatedAt\",\"kind\":\"scalar\",\"isList\":false,\"isRequired\":true,\"isUnique\":false,\"isId\":false,\"isReadOnly\":false,\"hasDefaultValue\":false,\"type\":\"DateTime\",\"isGenerated\":false,\"isUpdatedAt\":true}],\"primaryKey\":null,\"uniqueFields\":[],\"uniqueIndexes\":[],\"isGenerated\":false},\"EnergyContractDetails\":{\"dbName\":null,\"fields\":[{\"name\":\"id\",\"kind\":\"scalar\",\"isList\":false,\"isRequired\":true,\"isUnique\":false,\"isId\":true,\"isReadOnly\":false,\"hasDefaultValue\":true,\"type\":\"Int\",\"default\":{\"name\":\"autoincrement\",\"args\":[]},\"isGenerated\":false,\"isUpdatedAt\":false},{\"name\":\"contractId\",\"kind\":\"scalar\",\"isList\":false,\"isRequired\":true,\"isUnique\":true,\"isId\":false,\"isReadOnly\":true,\"hasDefaultValue\":false,\"type\":\"Int\",\"isGenerated\":false,\"isUpdatedAt\":false},{\"name\":\"contract\",\"kind\":\"object\",\"isList\":false,\"isRequired\":true,\"isUnique\":false,\"isId\":false,\"isReadOnly\":false,\"hasDefaultValue\":false,\"type\":\"Contract\",\"relationName\":\"ContractToEnergyContractDetails\",\"relationFromFields\":[\"contractId\"],\"relationToFields\":[\"id\"],\"relationOnDelete\":\"Cascade\",\"isGenerated\":false,\"isUpdatedAt\":false},{\"name\":\"meterId\",\"kind\":\"scalar\",\"isList\":false,\"isRequired\":false,\"isUnique\":false,\"isId\":false,\"isReadOnly\":true,\"hasDefaultValue\":false,\"type\":\"Int\",\"isGenerated\":false,\"isUpdatedAt\":false},{\"name\":\"meter\",\"kind\":\"object\",\"isList\":false,\"isRequired\":false,\"isUnique\":false,\"isId\":false,\"isReadOnly\":false,\"hasDefaultValue\":false,\"type\":\"Meter\",\"relationName\":\"EnergyContractDetailsToMeter\",\"relationFromFields\":[\"meterId\"],\"relationToFields\":[\"id\"],\"isGenerated\":false,\"isUpdatedAt\":false},{\"name\":\"annualConsumption\",\"kind\":\"scalar\",\"isList\":false,\"isRequired\":false,\"isUnique\":false,\"isId\":false,\"isReadOnly\":false,\"hasDefaultValue\":false,\"type\":\"Float\",\"isGenerated\":false,\"isUpdatedAt\":false},{\"name\":\"basePrice\",\"kind\":\"scalar\",\"isList\":false,\"isRequired\":false,\"isUnique\":false,\"isId\":false,\"isReadOnly\":false,\"hasDefaultValue\":false,\"type\":\"Float\",\"isGenerated\":false,\"isUpdatedAt\":false},{\"name\":\"unitPrice\",\"kind\":\"scalar\",\"isList\":false,\"isRequired\":false,\"isUnique\":false,\"isId\":false,\"isReadOnly\":false,\"hasDefaultValue\":false,\"type\":\"Float\",\"isGenerated\":false,\"isUpdatedAt\":false},{\"name\":\"bonus\",\"kind\":\"scalar\",\"isList\":false,\"isRequired\":false,\"isUnique\":false,\"isId\":false,\"isReadOnly\":false,\"hasDefaultValue\":false,\"type\":\"Float\",\"isGenerated\":false,\"isUpdatedAt\":false},{\"name\":\"previousProviderName\",\"kind\":\"scalar\",\"isList\":false,\"isRequired\":false,\"isUnique\":false,\"isId\":false,\"isReadOnly\":false,\"hasDefaultValue\":false,\"type\":\"String\",\"isGenerated\":false,\"isUpdatedAt\":false},{\"name\":\"previousCustomerNumber\",\"kind\":\"scalar\",\"isList\":false,\"isRequired\":false,\"isUnique\":false,\"isId\":false,\"isReadOnly\":false,\"hasDefaultValue\":false,\"type\":\"String\",\"isGenerated\":false,\"isUpdatedAt\":false}],\"primaryKey\":null,\"uniqueFields\":[],\"uniqueIndexes\":[],\"isGenerated\":false},\"InternetContractDetails\":{\"dbName\":null,\"fields\":[{\"name\":\"id\",\"kind\":\"scalar\",\"isList\":false,\"isRequired\":true,\"isUnique\":false,\"isId\":true,\"isReadOnly\":false,\"hasDefaultValue\":true,\"type\":\"Int\",\"default\":{\"name\":\"autoincrement\",\"args\":[]},\"isGenerated\":false,\"isUpdatedAt\":false},{\"name\":\"contractId\",\"kind\":\"scalar\",\"isList\":false,\"isRequired\":true,\"isUnique\":true,\"isId\":false,\"isReadOnly\":true,\"hasDefaultValue\":false,\"type\":\"Int\",\"isGenerated\":false,\"isUpdatedAt\":false},{\"name\":\"contract\",\"kind\":\"object\",\"isList\":false,\"isRequired\":true,\"isUnique\":false,\"isId\":false,\"isReadOnly\":false,\"hasDefaultValue\":false,\"type\":\"Contract\",\"relationName\":\"ContractToInternetContractDetails\",\"relationFromFields\":[\"contractId\"],\"relationToFields\":[\"id\"],\"relationOnDelete\":\"Cascade\",\"isGenerated\":false,\"isUpdatedAt\":false},{\"name\":\"downloadSpeed\",\"kind\":\"scalar\",\"isList\":false,\"isRequired\":false,\"isUnique\":false,\"isId\":false,\"isReadOnly\":false,\"hasDefaultValue\":false,\"type\":\"Int\",\"isGenerated\":false,\"isUpdatedAt\":false},{\"name\":\"uploadSpeed\",\"kind\":\"scalar\",\"isList\":false,\"isRequired\":false,\"isUnique\":false,\"isId\":false,\"isReadOnly\":false,\"hasDefaultValue\":false,\"type\":\"Int\",\"isGenerated\":false,\"isUpdatedAt\":false},{\"name\":\"routerModel\",\"kind\":\"scalar\",\"isList\":false,\"isRequired\":false,\"isUnique\":false,\"isId\":false,\"isReadOnly\":false,\"hasDefaultValue\":false,\"type\":\"String\",\"isGenerated\":false,\"isUpdatedAt\":false},{\"name\":\"routerSerialNumber\",\"kind\":\"scalar\",\"isList\":false,\"isRequired\":false,\"isUnique\":false,\"isId\":false,\"isReadOnly\":false,\"hasDefaultValue\":false,\"type\":\"String\",\"isGenerated\":false,\"isUpdatedAt\":false},{\"name\":\"installationDate\",\"kind\":\"scalar\",\"isList\":false,\"isRequired\":false,\"isUnique\":false,\"isId\":false,\"isReadOnly\":false,\"hasDefaultValue\":false,\"type\":\"DateTime\",\"isGenerated\":false,\"isUpdatedAt\":false},{\"name\":\"internetUsername\",\"kind\":\"scalar\",\"isList\":false,\"isRequired\":false,\"isUnique\":false,\"isId\":false,\"isReadOnly\":false,\"hasDefaultValue\":false,\"type\":\"String\",\"isGenerated\":false,\"isUpdatedAt\":false},{\"name\":\"internetPasswordEncrypted\",\"kind\":\"scalar\",\"isList\":false,\"isRequired\":false,\"isUnique\":false,\"isId\":false,\"isReadOnly\":false,\"hasDefaultValue\":false,\"type\":\"String\",\"isGenerated\":false,\"isUpdatedAt\":false},{\"name\":\"homeId\",\"kind\":\"scalar\",\"isList\":false,\"isRequired\":false,\"isUnique\":false,\"isId\":false,\"isReadOnly\":false,\"hasDefaultValue\":false,\"type\":\"String\",\"isGenerated\":false,\"isUpdatedAt\":false},{\"name\":\"activationCode\",\"kind\":\"scalar\",\"isList\":false,\"isRequired\":false,\"isUnique\":false,\"isId\":false,\"isReadOnly\":false,\"hasDefaultValue\":false,\"type\":\"String\",\"isGenerated\":false,\"isUpdatedAt\":false},{\"name\":\"phoneNumbers\",\"kind\":\"object\",\"isList\":true,\"isRequired\":true,\"isUnique\":false,\"isId\":false,\"isReadOnly\":false,\"hasDefaultValue\":false,\"type\":\"PhoneNumber\",\"relationName\":\"InternetContractDetailsToPhoneNumber\",\"relationFromFields\":[],\"relationToFields\":[],\"isGenerated\":false,\"isUpdatedAt\":false}],\"primaryKey\":null,\"uniqueFields\":[],\"uniqueIndexes\":[],\"isGenerated\":false},\"PhoneNumber\":{\"dbName\":null,\"fields\":[{\"name\":\"id\",\"kind\":\"scalar\",\"isList\":false,\"isRequired\":true,\"isUnique\":false,\"isId\":true,\"isReadOnly\":false,\"hasDefaultValue\":true,\"type\":\"Int\",\"default\":{\"name\":\"autoincrement\",\"args\":[]},\"isGenerated\":false,\"isUpdatedAt\":false},{\"name\":\"internetContractDetailsId\",\"kind\":\"scalar\",\"isList\":false,\"isRequired\":true,\"isUnique\":false,\"isId\":false,\"isReadOnly\":true,\"hasDefaultValue\":false,\"type\":\"Int\",\"isGenerated\":false,\"isUpdatedAt\":false},{\"name\":\"internetDetails\",\"kind\":\"object\",\"isList\":false,\"isRequired\":true,\"isUnique\":false,\"isId\":false,\"isReadOnly\":false,\"hasDefaultValue\":false,\"type\":\"InternetContractDetails\",\"relationName\":\"InternetContractDetailsToPhoneNumber\",\"relationFromFields\":[\"internetContractDetailsId\"],\"relationToFields\":[\"id\"],\"relationOnDelete\":\"Cascade\",\"isGenerated\":false,\"isUpdatedAt\":false},{\"name\":\"phoneNumber\",\"kind\":\"scalar\",\"isList\":false,\"isRequired\":true,\"isUnique\":false,\"isId\":false,\"isReadOnly\":false,\"hasDefaultValue\":false,\"type\":\"String\",\"isGenerated\":false,\"isUpdatedAt\":false},{\"name\":\"isMain\",\"kind\":\"scalar\",\"isList\":false,\"isRequired\":true,\"isUnique\":false,\"isId\":false,\"isReadOnly\":false,\"hasDefaultValue\":true,\"type\":\"Boolean\",\"default\":false,\"isGenerated\":false,\"isUpdatedAt\":false},{\"name\":\"sipUsername\",\"kind\":\"scalar\",\"isList\":false,\"isRequired\":false,\"isUnique\":false,\"isId\":false,\"isReadOnly\":false,\"hasDefaultValue\":false,\"type\":\"String\",\"isGenerated\":false,\"isUpdatedAt\":false},{\"name\":\"sipPasswordEncrypted\",\"kind\":\"scalar\",\"isList\":false,\"isRequired\":false,\"isUnique\":false,\"isId\":false,\"isReadOnly\":false,\"hasDefaultValue\":false,\"type\":\"String\",\"isGenerated\":false,\"isUpdatedAt\":false},{\"name\":\"sipServer\",\"kind\":\"scalar\",\"isList\":false,\"isRequired\":false,\"isUnique\":false,\"isId\":false,\"isReadOnly\":false,\"hasDefaultValue\":false,\"type\":\"String\",\"isGenerated\":false,\"isUpdatedAt\":false}],\"primaryKey\":null,\"uniqueFields\":[],\"uniqueIndexes\":[],\"isGenerated\":false},\"MobileContractDetails\":{\"dbName\":null,\"fields\":[{\"name\":\"id\",\"kind\":\"scalar\",\"isList\":false,\"isRequired\":true,\"isUnique\":false,\"isId\":true,\"isReadOnly\":false,\"hasDefaultValue\":true,\"type\":\"Int\",\"default\":{\"name\":\"autoincrement\",\"args\":[]},\"isGenerated\":false,\"isUpdatedAt\":false},{\"name\":\"contractId\",\"kind\":\"scalar\",\"isList\":false,\"isRequired\":true,\"isUnique\":true,\"isId\":false,\"isReadOnly\":true,\"hasDefaultValue\":false,\"type\":\"Int\",\"isGenerated\":false,\"isUpdatedAt\":false},{\"name\":\"contract\",\"kind\":\"object\",\"isList\":false,\"isRequired\":true,\"isUnique\":false,\"isId\":false,\"isReadOnly\":false,\"hasDefaultValue\":false,\"type\":\"Contract\",\"relationName\":\"ContractToMobileContractDetails\",\"relationFromFields\":[\"contractId\"],\"relationToFields\":[\"id\"],\"relationOnDelete\":\"Cascade\",\"isGenerated\":false,\"isUpdatedAt\":false},{\"name\":\"requiresMultisim\",\"kind\":\"scalar\",\"isList\":false,\"isRequired\":true,\"isUnique\":false,\"isId\":false,\"isReadOnly\":false,\"hasDefaultValue\":true,\"type\":\"Boolean\",\"default\":false,\"isGenerated\":false,\"isUpdatedAt\":false},{\"name\":\"dataVolume\",\"kind\":\"scalar\",\"isList\":false,\"isRequired\":false,\"isUnique\":false,\"isId\":false,\"isReadOnly\":false,\"hasDefaultValue\":false,\"type\":\"Float\",\"isGenerated\":false,\"isUpdatedAt\":false},{\"name\":\"includedMinutes\",\"kind\":\"scalar\",\"isList\":false,\"isRequired\":false,\"isUnique\":false,\"isId\":false,\"isReadOnly\":false,\"hasDefaultValue\":false,\"type\":\"Int\",\"isGenerated\":false,\"isUpdatedAt\":false},{\"name\":\"includedSMS\",\"kind\":\"scalar\",\"isList\":false,\"isRequired\":false,\"isUnique\":false,\"isId\":false,\"isReadOnly\":false,\"hasDefaultValue\":false,\"type\":\"Int\",\"isGenerated\":false,\"isUpdatedAt\":false},{\"name\":\"deviceModel\",\"kind\":\"scalar\",\"isList\":false,\"isRequired\":false,\"isUnique\":false,\"isId\":false,\"isReadOnly\":false,\"hasDefaultValue\":false,\"type\":\"String\",\"isGenerated\":false,\"isUpdatedAt\":false},{\"name\":\"deviceImei\",\"kind\":\"scalar\",\"isList\":false,\"isRequired\":false,\"isUnique\":false,\"isId\":false,\"isReadOnly\":false,\"hasDefaultValue\":false,\"type\":\"String\",\"isGenerated\":false,\"isUpdatedAt\":false},{\"name\":\"simCards\",\"kind\":\"object\",\"isList\":true,\"isRequired\":true,\"isUnique\":false,\"isId\":false,\"isReadOnly\":false,\"hasDefaultValue\":false,\"type\":\"SimCard\",\"relationName\":\"MobileContractDetailsToSimCard\",\"relationFromFields\":[],\"relationToFields\":[],\"isGenerated\":false,\"isUpdatedAt\":false},{\"name\":\"phoneNumber\",\"kind\":\"scalar\",\"isList\":false,\"isRequired\":false,\"isUnique\":false,\"isId\":false,\"isReadOnly\":false,\"hasDefaultValue\":false,\"type\":\"String\",\"isGenerated\":false,\"isUpdatedAt\":false},{\"name\":\"simCardNumber\",\"kind\":\"scalar\",\"isList\":false,\"isRequired\":false,\"isUnique\":false,\"isId\":false,\"isReadOnly\":false,\"hasDefaultValue\":false,\"type\":\"String\",\"isGenerated\":false,\"isUpdatedAt\":false}],\"primaryKey\":null,\"uniqueFields\":[],\"uniqueIndexes\":[],\"isGenerated\":false},\"SimCard\":{\"dbName\":null,\"fields\":[{\"name\":\"id\",\"kind\":\"scalar\",\"isList\":false,\"isRequired\":true,\"isUnique\":false,\"isId\":true,\"isReadOnly\":false,\"hasDefaultValue\":true,\"type\":\"Int\",\"default\":{\"name\":\"autoincrement\",\"args\":[]},\"isGenerated\":false,\"isUpdatedAt\":false},{\"name\":\"mobileDetailsId\",\"kind\":\"scalar\",\"isList\":false,\"isRequired\":true,\"isUnique\":false,\"isId\":false,\"isReadOnly\":true,\"hasDefaultValue\":false,\"type\":\"Int\",\"isGenerated\":false,\"isUpdatedAt\":false},{\"name\":\"mobileDetails\",\"kind\":\"object\",\"isList\":false,\"isRequired\":true,\"isUnique\":false,\"isId\":false,\"isReadOnly\":false,\"hasDefaultValue\":false,\"type\":\"MobileContractDetails\",\"relationName\":\"MobileContractDetailsToSimCard\",\"relationFromFields\":[\"mobileDetailsId\"],\"relationToFields\":[\"id\"],\"relationOnDelete\":\"Cascade\",\"isGenerated\":false,\"isUpdatedAt\":false},{\"name\":\"phoneNumber\",\"kind\":\"scalar\",\"isList\":false,\"isRequired\":false,\"isUnique\":false,\"isId\":false,\"isReadOnly\":false,\"hasDefaultValue\":false,\"type\":\"String\",\"isGenerated\":false,\"isUpdatedAt\":false},{\"name\":\"simCardNumber\",\"kind\":\"scalar\",\"isList\":false,\"isRequired\":false,\"isUnique\":false,\"isId\":false,\"isReadOnly\":false,\"hasDefaultValue\":false,\"type\":\"String\",\"isGenerated\":false,\"isUpdatedAt\":false},{\"name\":\"pin\",\"kind\":\"scalar\",\"isList\":false,\"isRequired\":false,\"isUnique\":false,\"isId\":false,\"isReadOnly\":false,\"hasDefaultValue\":false,\"type\":\"String\",\"isGenerated\":false,\"isUpdatedAt\":false},{\"name\":\"puk\",\"kind\":\"scalar\",\"isList\":false,\"isRequired\":false,\"isUnique\":false,\"isId\":false,\"isReadOnly\":false,\"hasDefaultValue\":false,\"type\":\"String\",\"isGenerated\":false,\"isUpdatedAt\":false},{\"name\":\"isMultisim\",\"kind\":\"scalar\",\"isList\":false,\"isRequired\":true,\"isUnique\":false,\"isId\":false,\"isReadOnly\":false,\"hasDefaultValue\":true,\"type\":\"Boolean\",\"default\":false,\"isGenerated\":false,\"isUpdatedAt\":false},{\"name\":\"isMain\",\"kind\":\"scalar\",\"isList\":false,\"isRequired\":true,\"isUnique\":false,\"isId\":false,\"isReadOnly\":false,\"hasDefaultValue\":true,\"type\":\"Boolean\",\"default\":false,\"isGenerated\":false,\"isUpdatedAt\":false},{\"name\":\"createdAt\",\"kind\":\"scalar\",\"isList\":false,\"isRequired\":true,\"isUnique\":false,\"isId\":false,\"isReadOnly\":false,\"hasDefaultValue\":true,\"type\":\"DateTime\",\"default\":{\"name\":\"now\",\"args\":[]},\"isGenerated\":false,\"isUpdatedAt\":false},{\"name\":\"updatedAt\",\"kind\":\"scalar\",\"isList\":false,\"isRequired\":true,\"isUnique\":false,\"isId\":false,\"isReadOnly\":false,\"hasDefaultValue\":false,\"type\":\"DateTime\",\"isGenerated\":false,\"isUpdatedAt\":true}],\"primaryKey\":null,\"uniqueFields\":[],\"uniqueIndexes\":[],\"isGenerated\":false},\"TvContractDetails\":{\"dbName\":null,\"fields\":[{\"name\":\"id\",\"kind\":\"scalar\",\"isList\":false,\"isRequired\":true,\"isUnique\":false,\"isId\":true,\"isReadOnly\":false,\"hasDefaultValue\":true,\"type\":\"Int\",\"default\":{\"name\":\"autoincrement\",\"args\":[]},\"isGenerated\":false,\"isUpdatedAt\":false},{\"name\":\"contractId\",\"kind\":\"scalar\",\"isList\":false,\"isRequired\":true,\"isUnique\":true,\"isId\":false,\"isReadOnly\":true,\"hasDefaultValue\":false,\"type\":\"Int\",\"isGenerated\":false,\"isUpdatedAt\":false},{\"name\":\"contract\",\"kind\":\"object\",\"isList\":false,\"isRequired\":true,\"isUnique\":false,\"isId\":false,\"isReadOnly\":false,\"hasDefaultValue\":false,\"type\":\"Contract\",\"relationName\":\"ContractToTvContractDetails\",\"relationFromFields\":[\"contractId\"],\"relationToFields\":[\"id\"],\"relationOnDelete\":\"Cascade\",\"isGenerated\":false,\"isUpdatedAt\":false},{\"name\":\"receiverModel\",\"kind\":\"scalar\",\"isList\":false,\"isRequired\":false,\"isUnique\":false,\"isId\":false,\"isReadOnly\":false,\"hasDefaultValue\":false,\"type\":\"String\",\"isGenerated\":false,\"isUpdatedAt\":false},{\"name\":\"smartcardNumber\",\"kind\":\"scalar\",\"isList\":false,\"isRequired\":false,\"isUnique\":false,\"isId\":false,\"isReadOnly\":false,\"hasDefaultValue\":false,\"type\":\"String\",\"isGenerated\":false,\"isUpdatedAt\":false},{\"name\":\"package\",\"kind\":\"scalar\",\"isList\":false,\"isRequired\":false,\"isUnique\":false,\"isId\":false,\"isReadOnly\":false,\"hasDefaultValue\":false,\"type\":\"String\",\"isGenerated\":false,\"isUpdatedAt\":false}],\"primaryKey\":null,\"uniqueFields\":[],\"uniqueIndexes\":[],\"isGenerated\":false},\"CarInsuranceDetails\":{\"dbName\":null,\"fields\":[{\"name\":\"id\",\"kind\":\"scalar\",\"isList\":false,\"isRequired\":true,\"isUnique\":false,\"isId\":true,\"isReadOnly\":false,\"hasDefaultValue\":true,\"type\":\"Int\",\"default\":{\"name\":\"autoincrement\",\"args\":[]},\"isGenerated\":false,\"isUpdatedAt\":false},{\"name\":\"contractId\",\"kind\":\"scalar\",\"isList\":false,\"isRequired\":true,\"isUnique\":true,\"isId\":false,\"isReadOnly\":true,\"hasDefaultValue\":false,\"type\":\"Int\",\"isGenerated\":false,\"isUpdatedAt\":false},{\"name\":\"contract\",\"kind\":\"object\",\"isList\":false,\"isRequired\":true,\"isUnique\":false,\"isId\":false,\"isReadOnly\":false,\"hasDefaultValue\":false,\"type\":\"Contract\",\"relationName\":\"CarInsuranceDetailsToContract\",\"relationFromFields\":[\"contractId\"],\"relationToFields\":[\"id\"],\"relationOnDelete\":\"Cascade\",\"isGenerated\":false,\"isUpdatedAt\":false},{\"name\":\"licensePlate\",\"kind\":\"scalar\",\"isList\":false,\"isRequired\":false,\"isUnique\":false,\"isId\":false,\"isReadOnly\":false,\"hasDefaultValue\":false,\"type\":\"String\",\"isGenerated\":false,\"isUpdatedAt\":false},{\"name\":\"hsn\",\"kind\":\"scalar\",\"isList\":false,\"isRequired\":false,\"isUnique\":false,\"isId\":false,\"isReadOnly\":false,\"hasDefaultValue\":false,\"type\":\"String\",\"isGenerated\":false,\"isUpdatedAt\":false},{\"name\":\"tsn\",\"kind\":\"scalar\",\"isList\":false,\"isRequired\":false,\"isUnique\":false,\"isId\":false,\"isReadOnly\":false,\"hasDefaultValue\":false,\"type\":\"String\",\"isGenerated\":false,\"isUpdatedAt\":false},{\"name\":\"vin\",\"kind\":\"scalar\",\"isList\":false,\"isRequired\":false,\"isUnique\":false,\"isId\":false,\"isReadOnly\":false,\"hasDefaultValue\":false,\"type\":\"String\",\"isGenerated\":false,\"isUpdatedAt\":false},{\"name\":\"vehicleType\",\"kind\":\"scalar\",\"isList\":false,\"isRequired\":false,\"isUnique\":false,\"isId\":false,\"isReadOnly\":false,\"hasDefaultValue\":false,\"type\":\"String\",\"isGenerated\":false,\"isUpdatedAt\":false},{\"name\":\"firstRegistration\",\"kind\":\"scalar\",\"isList\":false,\"isRequired\":false,\"isUnique\":false,\"isId\":false,\"isReadOnly\":false,\"hasDefaultValue\":false,\"type\":\"DateTime\",\"isGenerated\":false,\"isUpdatedAt\":false},{\"name\":\"noClaimsClass\",\"kind\":\"scalar\",\"isList\":false,\"isRequired\":false,\"isUnique\":false,\"isId\":false,\"isReadOnly\":false,\"hasDefaultValue\":false,\"type\":\"String\",\"isGenerated\":false,\"isUpdatedAt\":false},{\"name\":\"insuranceType\",\"kind\":\"enum\",\"isList\":false,\"isRequired\":true,\"isUnique\":false,\"isId\":false,\"isReadOnly\":false,\"hasDefaultValue\":true,\"type\":\"InsuranceType\",\"default\":\"LIABILITY\",\"isGenerated\":false,\"isUpdatedAt\":false},{\"name\":\"deductiblePartial\",\"kind\":\"scalar\",\"isList\":false,\"isRequired\":false,\"isUnique\":false,\"isId\":false,\"isReadOnly\":false,\"hasDefaultValue\":false,\"type\":\"Float\",\"isGenerated\":false,\"isUpdatedAt\":false},{\"name\":\"deductibleFull\",\"kind\":\"scalar\",\"isList\":false,\"isRequired\":false,\"isUnique\":false,\"isId\":false,\"isReadOnly\":false,\"hasDefaultValue\":false,\"type\":\"Float\",\"isGenerated\":false,\"isUpdatedAt\":false},{\"name\":\"policyNumber\",\"kind\":\"scalar\",\"isList\":false,\"isRequired\":false,\"isUnique\":false,\"isId\":false,\"isReadOnly\":false,\"hasDefaultValue\":false,\"type\":\"String\",\"isGenerated\":false,\"isUpdatedAt\":false},{\"name\":\"previousInsurer\",\"kind\":\"scalar\",\"isList\":false,\"isRequired\":false,\"isUnique\":false,\"isId\":false,\"isReadOnly\":false,\"hasDefaultValue\":false,\"type\":\"String\",\"isGenerated\":false,\"isUpdatedAt\":false}],\"primaryKey\":null,\"uniqueFields\":[],\"uniqueIndexes\":[],\"isGenerated\":false}},\"enums\":{\"CustomerType\":{\"values\":[{\"name\":\"PRIVATE\",\"dbName\":null},{\"name\":\"BUSINESS\",\"dbName\":null}],\"dbName\":null},\"AddressType\":{\"values\":[{\"name\":\"DELIVERY_RESIDENCE\",\"dbName\":null},{\"name\":\"BILLING\",\"dbName\":null}],\"dbName\":null},\"DocumentType\":{\"values\":[{\"name\":\"ID_CARD\",\"dbName\":null},{\"name\":\"PASSPORT\",\"dbName\":null},{\"name\":\"DRIVERS_LICENSE\",\"dbName\":null},{\"name\":\"OTHER\",\"dbName\":null}],\"dbName\":null},\"EmailProviderType\":{\"values\":[{\"name\":\"PLESK\",\"dbName\":null},{\"name\":\"CPANEL\",\"dbName\":null},{\"name\":\"DIRECTADMIN\",\"dbName\":null}],\"dbName\":null},\"MailEncryption\":{\"values\":[{\"name\":\"SSL\",\"dbName\":null},{\"name\":\"STARTTLS\",\"dbName\":null},{\"name\":\"NONE\",\"dbName\":null}],\"dbName\":null},\"EmailFolder\":{\"values\":[{\"name\":\"INBOX\",\"dbName\":null},{\"name\":\"SENT\",\"dbName\":null}],\"dbName\":null},\"MeterType\":{\"values\":[{\"name\":\"ELECTRICITY\",\"dbName\":null},{\"name\":\"GAS\",\"dbName\":null}],\"dbName\":null},\"ContractType\":{\"values\":[{\"name\":\"ELECTRICITY\",\"dbName\":null},{\"name\":\"GAS\",\"dbName\":null},{\"name\":\"DSL\",\"dbName\":null},{\"name\":\"CABLE\",\"dbName\":null},{\"name\":\"FIBER\",\"dbName\":null},{\"name\":\"MOBILE\",\"dbName\":null},{\"name\":\"TV\",\"dbName\":null},{\"name\":\"CAR_INSURANCE\",\"dbName\":null}],\"dbName\":null},\"ContractStatus\":{\"values\":[{\"name\":\"DRAFT\",\"dbName\":null},{\"name\":\"PENDING\",\"dbName\":null},{\"name\":\"ACTIVE\",\"dbName\":null},{\"name\":\"CANCELLED\",\"dbName\":null},{\"name\":\"EXPIRED\",\"dbName\":null},{\"name\":\"DEACTIVATED\",\"dbName\":null}],\"dbName\":null},\"ContractTaskStatus\":{\"values\":[{\"name\":\"OPEN\",\"dbName\":null},{\"name\":\"COMPLETED\",\"dbName\":null}],\"dbName\":null},\"InsuranceType\":{\"values\":[{\"name\":\"LIABILITY\",\"dbName\":null},{\"name\":\"PARTIAL\",\"dbName\":null},{\"name\":\"FULL\",\"dbName\":null}],\"dbName\":null}},\"types\":{}}") defineDmmfProperty(exports.Prisma, config.runtimeDataModel) config.engineWasm = undefined diff --git a/backend/node_modules/.prisma/client/index-browser.js b/backend/node_modules/.prisma/client/index-browser.js index 788cdf87..f2d10b1d 100644 --- a/backend/node_modules/.prisma/client/index-browser.js +++ b/backend/node_modules/.prisma/client/index-browser.js @@ -137,6 +137,7 @@ exports.Prisma.UserScalarFieldEnum = { firstName: 'firstName', lastName: 'lastName', isActive: 'isActive', + tokenInvalidatedAt: 'tokenInvalidatedAt', customerId: 'customerId', createdAt: 'createdAt', updatedAt: 'updatedAt' @@ -259,6 +260,13 @@ exports.Prisma.EmailProviderConfigScalarFieldEnum = { passwordEncrypted: 'passwordEncrypted', domain: 'domain', defaultForwardEmail: 'defaultForwardEmail', + imapServer: 'imapServer', + imapPort: 'imapPort', + smtpServer: 'smtpServer', + smtpPort: 'smtpPort', + imapEncryption: 'imapEncryption', + smtpEncryption: 'smtpEncryption', + allowSelfSignedCerts: 'allowSelfSignedCerts', isActive: 'isActive', isDefault: 'isDefault', createdAt: 'createdAt', @@ -275,6 +283,36 @@ exports.Prisma.StressfreiEmailScalarFieldEnum = { isProvisioned: 'isProvisioned', provisionedAt: 'provisionedAt', provisionError: 'provisionError', + hasMailbox: 'hasMailbox', + emailPasswordEncrypted: 'emailPasswordEncrypted', + createdAt: 'createdAt', + updatedAt: 'updatedAt' +}; + +exports.Prisma.CachedEmailScalarFieldEnum = { + id: 'id', + stressfreiEmailId: 'stressfreiEmailId', + folder: 'folder', + messageId: 'messageId', + uid: 'uid', + subject: 'subject', + fromAddress: 'fromAddress', + fromName: 'fromName', + toAddresses: 'toAddresses', + ccAddresses: 'ccAddresses', + receivedAt: 'receivedAt', + textBody: 'textBody', + htmlBody: 'htmlBody', + hasAttachments: 'hasAttachments', + attachmentNames: 'attachmentNames', + contractId: 'contractId', + assignedAt: 'assignedAt', + assignedBy: 'assignedBy', + isAutoAssigned: 'isAutoAssigned', + isRead: 'isRead', + isStarred: 'isStarred', + isDeleted: 'isDeleted', + deletedAt: 'deletedAt', createdAt: 'createdAt', updatedAt: 'updatedAt' }; @@ -542,6 +580,17 @@ exports.EmailProviderType = exports.$Enums.EmailProviderType = { DIRECTADMIN: 'DIRECTADMIN' }; +exports.MailEncryption = exports.$Enums.MailEncryption = { + SSL: 'SSL', + STARTTLS: 'STARTTLS', + NONE: 'NONE' +}; + +exports.EmailFolder = exports.$Enums.EmailFolder = { + INBOX: 'INBOX', + SENT: 'SENT' +}; + exports.MeterType = exports.$Enums.MeterType = { ELECTRICITY: 'ELECTRICITY', GAS: 'GAS' @@ -592,6 +641,7 @@ exports.Prisma.ModelName = { IdentityDocument: 'IdentityDocument', EmailProviderConfig: 'EmailProviderConfig', StressfreiEmail: 'StressfreiEmail', + CachedEmail: 'CachedEmail', Meter: 'Meter', MeterReading: 'MeterReading', SalesPlatform: 'SalesPlatform', diff --git a/backend/node_modules/.prisma/client/index.d.ts b/backend/node_modules/.prisma/client/index.d.ts index 938e39df..6764fc5c 100644 --- a/backend/node_modules/.prisma/client/index.d.ts +++ b/backend/node_modules/.prisma/client/index.d.ts @@ -78,6 +78,11 @@ export type EmailProviderConfig = $Result.DefaultSelection +/** + * Model CachedEmail + * + */ +export type CachedEmail = $Result.DefaultSelection /** * Model Meter * @@ -208,6 +213,23 @@ export const EmailProviderType: { export type EmailProviderType = (typeof EmailProviderType)[keyof typeof EmailProviderType] +export const MailEncryption: { + SSL: 'SSL', + STARTTLS: 'STARTTLS', + NONE: 'NONE' +}; + +export type MailEncryption = (typeof MailEncryption)[keyof typeof MailEncryption] + + +export const EmailFolder: { + INBOX: 'INBOX', + SENT: 'SENT' +}; + +export type EmailFolder = (typeof EmailFolder)[keyof typeof EmailFolder] + + export const MeterType: { ELECTRICITY: 'ELECTRICITY', GAS: 'GAS' @@ -276,6 +298,14 @@ export type EmailProviderType = $Enums.EmailProviderType export const EmailProviderType: typeof $Enums.EmailProviderType +export type MailEncryption = $Enums.MailEncryption + +export const MailEncryption: typeof $Enums.MailEncryption + +export type EmailFolder = $Enums.EmailFolder + +export const EmailFolder: typeof $Enums.EmailFolder + export type MeterType = $Enums.MeterType export const MeterType: typeof $Enums.MeterType @@ -549,6 +579,16 @@ export class PrismaClient< */ get stressfreiEmail(): Prisma.StressfreiEmailDelegate; + /** + * `prisma.cachedEmail`: Exposes CRUD operations for the **CachedEmail** model. + * Example usage: + * ```ts + * // Fetch zero or more CachedEmails + * const cachedEmails = await prisma.cachedEmail.findMany() + * ``` + */ + get cachedEmail(): Prisma.CachedEmailDelegate; + /** * `prisma.meter`: Exposes CRUD operations for the **Meter** model. * Example usage: @@ -1182,6 +1222,7 @@ export namespace Prisma { IdentityDocument: 'IdentityDocument', EmailProviderConfig: 'EmailProviderConfig', StressfreiEmail: 'StressfreiEmail', + CachedEmail: 'CachedEmail', Meter: 'Meter', MeterReading: 'MeterReading', SalesPlatform: 'SalesPlatform', @@ -1215,7 +1256,7 @@ export namespace Prisma { export type TypeMap = { meta: { - modelProps: "appSetting" | "user" | "role" | "permission" | "rolePermission" | "userRole" | "customer" | "customerRepresentative" | "address" | "bankCard" | "identityDocument" | "emailProviderConfig" | "stressfreiEmail" | "meter" | "meterReading" | "salesPlatform" | "cancellationPeriod" | "contractDuration" | "provider" | "tariff" | "contractCategory" | "contract" | "contractTask" | "contractTaskSubtask" | "energyContractDetails" | "internetContractDetails" | "phoneNumber" | "mobileContractDetails" | "simCard" | "tvContractDetails" | "carInsuranceDetails" + modelProps: "appSetting" | "user" | "role" | "permission" | "rolePermission" | "userRole" | "customer" | "customerRepresentative" | "address" | "bankCard" | "identityDocument" | "emailProviderConfig" | "stressfreiEmail" | "cachedEmail" | "meter" | "meterReading" | "salesPlatform" | "cancellationPeriod" | "contractDuration" | "provider" | "tariff" | "contractCategory" | "contract" | "contractTask" | "contractTaskSubtask" | "energyContractDetails" | "internetContractDetails" | "phoneNumber" | "mobileContractDetails" | "simCard" | "tvContractDetails" | "carInsuranceDetails" txIsolationLevel: Prisma.TransactionIsolationLevel } model: { @@ -2077,6 +2118,72 @@ export namespace Prisma { } } } + CachedEmail: { + payload: Prisma.$CachedEmailPayload + fields: Prisma.CachedEmailFieldRefs + operations: { + findUnique: { + args: Prisma.CachedEmailFindUniqueArgs + result: $Utils.PayloadToResult | null + } + findUniqueOrThrow: { + args: Prisma.CachedEmailFindUniqueOrThrowArgs + result: $Utils.PayloadToResult + } + findFirst: { + args: Prisma.CachedEmailFindFirstArgs + result: $Utils.PayloadToResult | null + } + findFirstOrThrow: { + args: Prisma.CachedEmailFindFirstOrThrowArgs + result: $Utils.PayloadToResult + } + findMany: { + args: Prisma.CachedEmailFindManyArgs + result: $Utils.PayloadToResult[] + } + create: { + args: Prisma.CachedEmailCreateArgs + result: $Utils.PayloadToResult + } + createMany: { + args: Prisma.CachedEmailCreateManyArgs + result: BatchPayload + } + delete: { + args: Prisma.CachedEmailDeleteArgs + result: $Utils.PayloadToResult + } + update: { + args: Prisma.CachedEmailUpdateArgs + result: $Utils.PayloadToResult + } + deleteMany: { + args: Prisma.CachedEmailDeleteManyArgs + result: BatchPayload + } + updateMany: { + args: Prisma.CachedEmailUpdateManyArgs + result: BatchPayload + } + upsert: { + args: Prisma.CachedEmailUpsertArgs + result: $Utils.PayloadToResult + } + aggregate: { + args: Prisma.CachedEmailAggregateArgs + result: $Utils.Optional + } + groupBy: { + args: Prisma.CachedEmailGroupByArgs + result: $Utils.Optional[] + } + count: { + args: Prisma.CachedEmailCountArgs + result: $Utils.Optional | number + } + } + } Meter: { payload: Prisma.$MeterPayload fields: Prisma.MeterFieldRefs @@ -3716,10 +3823,12 @@ export namespace Prisma { export type StressfreiEmailCountOutputType = { contracts: number + cachedEmails: number } export type StressfreiEmailCountOutputTypeSelect = { contracts?: boolean | StressfreiEmailCountOutputTypeCountContractsArgs + cachedEmails?: boolean | StressfreiEmailCountOutputTypeCountCachedEmailsArgs } // Custom InputTypes @@ -3740,6 +3849,13 @@ export namespace Prisma { where?: ContractWhereInput } + /** + * StressfreiEmailCountOutputType without action + */ + export type StressfreiEmailCountOutputTypeCountCachedEmailsArgs = { + where?: CachedEmailWhereInput + } + /** * Count Type MeterCountOutputType @@ -3982,10 +4098,12 @@ export namespace Prisma { export type ContractCountOutputType = { tasks: number + assignedEmails: number } export type ContractCountOutputTypeSelect = { tasks?: boolean | ContractCountOutputTypeCountTasksArgs + assignedEmails?: boolean | ContractCountOutputTypeCountAssignedEmailsArgs } // Custom InputTypes @@ -4006,6 +4124,13 @@ export namespace Prisma { where?: ContractTaskWhereInput } + /** + * ContractCountOutputType without action + */ + export type ContractCountOutputTypeCountAssignedEmailsArgs = { + where?: CachedEmailWhereInput + } + /** * Count Type ContractTaskCountOutputType @@ -4999,6 +5124,7 @@ export namespace Prisma { firstName: string | null lastName: string | null isActive: boolean | null + tokenInvalidatedAt: Date | null customerId: number | null createdAt: Date | null updatedAt: Date | null @@ -5011,6 +5137,7 @@ export namespace Prisma { firstName: string | null lastName: string | null isActive: boolean | null + tokenInvalidatedAt: Date | null customerId: number | null createdAt: Date | null updatedAt: Date | null @@ -5023,6 +5150,7 @@ export namespace Prisma { firstName: number lastName: number isActive: number + tokenInvalidatedAt: number customerId: number createdAt: number updatedAt: number @@ -5047,6 +5175,7 @@ export namespace Prisma { firstName?: true lastName?: true isActive?: true + tokenInvalidatedAt?: true customerId?: true createdAt?: true updatedAt?: true @@ -5059,6 +5188,7 @@ export namespace Prisma { firstName?: true lastName?: true isActive?: true + tokenInvalidatedAt?: true customerId?: true createdAt?: true updatedAt?: true @@ -5071,6 +5201,7 @@ export namespace Prisma { firstName?: true lastName?: true isActive?: true + tokenInvalidatedAt?: true customerId?: true createdAt?: true updatedAt?: true @@ -5170,6 +5301,7 @@ export namespace Prisma { firstName: string lastName: string isActive: boolean + tokenInvalidatedAt: Date | null customerId: number | null createdAt: Date updatedAt: Date @@ -5201,6 +5333,7 @@ export namespace Prisma { firstName?: boolean lastName?: boolean isActive?: boolean + tokenInvalidatedAt?: boolean customerId?: boolean createdAt?: boolean updatedAt?: boolean @@ -5217,6 +5350,7 @@ export namespace Prisma { firstName?: boolean lastName?: boolean isActive?: boolean + tokenInvalidatedAt?: boolean customerId?: boolean createdAt?: boolean updatedAt?: boolean @@ -5241,6 +5375,7 @@ export namespace Prisma { firstName: string lastName: string isActive: boolean + tokenInvalidatedAt: Date | null customerId: number | null createdAt: Date updatedAt: Date @@ -5621,6 +5756,7 @@ export namespace Prisma { readonly firstName: FieldRef<"User", 'String'> readonly lastName: FieldRef<"User", 'String'> readonly isActive: FieldRef<"User", 'Boolean'> + readonly tokenInvalidatedAt: FieldRef<"User", 'DateTime'> readonly customerId: FieldRef<"User", 'Int'> readonly createdAt: FieldRef<"User", 'DateTime'> readonly updatedAt: FieldRef<"User", 'DateTime'> @@ -14983,10 +15119,14 @@ export namespace Prisma { export type EmailProviderConfigAvgAggregateOutputType = { id: number | null + imapPort: number | null + smtpPort: number | null } export type EmailProviderConfigSumAggregateOutputType = { id: number | null + imapPort: number | null + smtpPort: number | null } export type EmailProviderConfigMinAggregateOutputType = { @@ -14999,6 +15139,13 @@ export namespace Prisma { passwordEncrypted: string | null domain: string | null defaultForwardEmail: string | null + imapServer: string | null + imapPort: number | null + smtpServer: string | null + smtpPort: number | null + imapEncryption: $Enums.MailEncryption | null + smtpEncryption: $Enums.MailEncryption | null + allowSelfSignedCerts: boolean | null isActive: boolean | null isDefault: boolean | null createdAt: Date | null @@ -15015,6 +15162,13 @@ export namespace Prisma { passwordEncrypted: string | null domain: string | null defaultForwardEmail: string | null + imapServer: string | null + imapPort: number | null + smtpServer: string | null + smtpPort: number | null + imapEncryption: $Enums.MailEncryption | null + smtpEncryption: $Enums.MailEncryption | null + allowSelfSignedCerts: boolean | null isActive: boolean | null isDefault: boolean | null createdAt: Date | null @@ -15031,6 +15185,13 @@ export namespace Prisma { passwordEncrypted: number domain: number defaultForwardEmail: number + imapServer: number + imapPort: number + smtpServer: number + smtpPort: number + imapEncryption: number + smtpEncryption: number + allowSelfSignedCerts: number isActive: number isDefault: number createdAt: number @@ -15041,10 +15202,14 @@ export namespace Prisma { export type EmailProviderConfigAvgAggregateInputType = { id?: true + imapPort?: true + smtpPort?: true } export type EmailProviderConfigSumAggregateInputType = { id?: true + imapPort?: true + smtpPort?: true } export type EmailProviderConfigMinAggregateInputType = { @@ -15057,6 +15222,13 @@ export namespace Prisma { passwordEncrypted?: true domain?: true defaultForwardEmail?: true + imapServer?: true + imapPort?: true + smtpServer?: true + smtpPort?: true + imapEncryption?: true + smtpEncryption?: true + allowSelfSignedCerts?: true isActive?: true isDefault?: true createdAt?: true @@ -15073,6 +15245,13 @@ export namespace Prisma { passwordEncrypted?: true domain?: true defaultForwardEmail?: true + imapServer?: true + imapPort?: true + smtpServer?: true + smtpPort?: true + imapEncryption?: true + smtpEncryption?: true + allowSelfSignedCerts?: true isActive?: true isDefault?: true createdAt?: true @@ -15089,6 +15268,13 @@ export namespace Prisma { passwordEncrypted?: true domain?: true defaultForwardEmail?: true + imapServer?: true + imapPort?: true + smtpServer?: true + smtpPort?: true + imapEncryption?: true + smtpEncryption?: true + allowSelfSignedCerts?: true isActive?: true isDefault?: true createdAt?: true @@ -15192,6 +15378,13 @@ export namespace Prisma { passwordEncrypted: string | null domain: string defaultForwardEmail: string | null + imapServer: string | null + imapPort: number | null + smtpServer: string | null + smtpPort: number | null + imapEncryption: $Enums.MailEncryption + smtpEncryption: $Enums.MailEncryption + allowSelfSignedCerts: boolean isActive: boolean isDefault: boolean createdAt: Date @@ -15227,6 +15420,13 @@ export namespace Prisma { passwordEncrypted?: boolean domain?: boolean defaultForwardEmail?: boolean + imapServer?: boolean + imapPort?: boolean + smtpServer?: boolean + smtpPort?: boolean + imapEncryption?: boolean + smtpEncryption?: boolean + allowSelfSignedCerts?: boolean isActive?: boolean isDefault?: boolean createdAt?: boolean @@ -15244,6 +15444,13 @@ export namespace Prisma { passwordEncrypted?: boolean domain?: boolean defaultForwardEmail?: boolean + imapServer?: boolean + imapPort?: boolean + smtpServer?: boolean + smtpPort?: boolean + imapEncryption?: boolean + smtpEncryption?: boolean + allowSelfSignedCerts?: boolean isActive?: boolean isDefault?: boolean createdAt?: boolean @@ -15264,6 +15471,13 @@ export namespace Prisma { passwordEncrypted: string | null domain: string defaultForwardEmail: string | null + imapServer: string | null + imapPort: number | null + smtpServer: string | null + smtpPort: number | null + imapEncryption: $Enums.MailEncryption + smtpEncryption: $Enums.MailEncryption + allowSelfSignedCerts: boolean isActive: boolean isDefault: boolean createdAt: Date @@ -15646,6 +15860,13 @@ export namespace Prisma { readonly passwordEncrypted: FieldRef<"EmailProviderConfig", 'String'> readonly domain: FieldRef<"EmailProviderConfig", 'String'> readonly defaultForwardEmail: FieldRef<"EmailProviderConfig", 'String'> + readonly imapServer: FieldRef<"EmailProviderConfig", 'String'> + readonly imapPort: FieldRef<"EmailProviderConfig", 'Int'> + readonly smtpServer: FieldRef<"EmailProviderConfig", 'String'> + readonly smtpPort: FieldRef<"EmailProviderConfig", 'Int'> + readonly imapEncryption: FieldRef<"EmailProviderConfig", 'MailEncryption'> + readonly smtpEncryption: FieldRef<"EmailProviderConfig", 'MailEncryption'> + readonly allowSelfSignedCerts: FieldRef<"EmailProviderConfig", 'Boolean'> readonly isActive: FieldRef<"EmailProviderConfig", 'Boolean'> readonly isDefault: FieldRef<"EmailProviderConfig", 'Boolean'> readonly createdAt: FieldRef<"EmailProviderConfig", 'DateTime'> @@ -15955,6 +16176,8 @@ export namespace Prisma { isProvisioned: boolean | null provisionedAt: Date | null provisionError: string | null + hasMailbox: boolean | null + emailPasswordEncrypted: string | null createdAt: Date | null updatedAt: Date | null } @@ -15969,6 +16192,8 @@ export namespace Prisma { isProvisioned: boolean | null provisionedAt: Date | null provisionError: string | null + hasMailbox: boolean | null + emailPasswordEncrypted: string | null createdAt: Date | null updatedAt: Date | null } @@ -15983,6 +16208,8 @@ export namespace Prisma { isProvisioned: number provisionedAt: number provisionError: number + hasMailbox: number + emailPasswordEncrypted: number createdAt: number updatedAt: number _all: number @@ -16009,6 +16236,8 @@ export namespace Prisma { isProvisioned?: true provisionedAt?: true provisionError?: true + hasMailbox?: true + emailPasswordEncrypted?: true createdAt?: true updatedAt?: true } @@ -16023,6 +16252,8 @@ export namespace Prisma { isProvisioned?: true provisionedAt?: true provisionError?: true + hasMailbox?: true + emailPasswordEncrypted?: true createdAt?: true updatedAt?: true } @@ -16037,6 +16268,8 @@ export namespace Prisma { isProvisioned?: true provisionedAt?: true provisionError?: true + hasMailbox?: true + emailPasswordEncrypted?: true createdAt?: true updatedAt?: true _all?: true @@ -16138,6 +16371,8 @@ export namespace Prisma { isProvisioned: boolean provisionedAt: Date | null provisionError: string | null + hasMailbox: boolean + emailPasswordEncrypted: string | null createdAt: Date updatedAt: Date _count: StressfreiEmailCountAggregateOutputType | null @@ -16171,10 +16406,13 @@ export namespace Prisma { isProvisioned?: boolean provisionedAt?: boolean provisionError?: boolean + hasMailbox?: boolean + emailPasswordEncrypted?: boolean createdAt?: boolean updatedAt?: boolean customer?: boolean | CustomerDefaultArgs contracts?: boolean | StressfreiEmail$contractsArgs + cachedEmails?: boolean | StressfreiEmail$cachedEmailsArgs _count?: boolean | StressfreiEmailCountOutputTypeDefaultArgs }, ExtArgs["result"]["stressfreiEmail"]> @@ -16189,6 +16427,8 @@ export namespace Prisma { isProvisioned?: boolean provisionedAt?: boolean provisionError?: boolean + hasMailbox?: boolean + emailPasswordEncrypted?: boolean createdAt?: boolean updatedAt?: boolean } @@ -16196,6 +16436,7 @@ export namespace Prisma { export type StressfreiEmailInclude = { customer?: boolean | CustomerDefaultArgs contracts?: boolean | StressfreiEmail$contractsArgs + cachedEmails?: boolean | StressfreiEmail$cachedEmailsArgs _count?: boolean | StressfreiEmailCountOutputTypeDefaultArgs } @@ -16204,6 +16445,7 @@ export namespace Prisma { objects: { customer: Prisma.$CustomerPayload contracts: Prisma.$ContractPayload[] + cachedEmails: Prisma.$CachedEmailPayload[] } scalars: $Extensions.GetPayloadResult<{ id: number @@ -16215,6 +16457,8 @@ export namespace Prisma { isProvisioned: boolean provisionedAt: Date | null provisionError: string | null + hasMailbox: boolean + emailPasswordEncrypted: string | null createdAt: Date updatedAt: Date }, ExtArgs["result"]["stressfreiEmail"]> @@ -16559,6 +16803,7 @@ export namespace Prisma { readonly [Symbol.toStringTag]: "PrismaPromise" customer = {}>(args?: Subset>): Prisma__CustomerClient<$Result.GetResult, T, "findUniqueOrThrow"> | Null, Null, ExtArgs> contracts = {}>(args?: Subset>): Prisma.PrismaPromise<$Result.GetResult, T, "findMany"> | Null> + cachedEmails = {}>(args?: Subset>): Prisma.PrismaPromise<$Result.GetResult, T, "findMany"> | Null> /** * Attaches callbacks for the resolution and/or rejection of the Promise. * @param onfulfilled The callback to execute when the Promise is resolved. @@ -16597,6 +16842,8 @@ export namespace Prisma { readonly isProvisioned: FieldRef<"StressfreiEmail", 'Boolean'> readonly provisionedAt: FieldRef<"StressfreiEmail", 'DateTime'> readonly provisionError: FieldRef<"StressfreiEmail", 'String'> + readonly hasMailbox: FieldRef<"StressfreiEmail", 'Boolean'> + readonly emailPasswordEncrypted: FieldRef<"StressfreiEmail", 'String'> readonly createdAt: FieldRef<"StressfreiEmail", 'DateTime'> readonly updatedAt: FieldRef<"StressfreiEmail", 'DateTime'> } @@ -16917,6 +17164,26 @@ export namespace Prisma { distinct?: ContractScalarFieldEnum | ContractScalarFieldEnum[] } + /** + * StressfreiEmail.cachedEmails + */ + export type StressfreiEmail$cachedEmailsArgs = { + /** + * Select specific fields to fetch from the CachedEmail + */ + select?: CachedEmailSelect | null + /** + * Choose, which related nodes to fetch as well + */ + include?: CachedEmailInclude | null + where?: CachedEmailWhereInput + orderBy?: CachedEmailOrderByWithRelationInput | CachedEmailOrderByWithRelationInput[] + cursor?: CachedEmailWhereUniqueInput + take?: number + skip?: number + distinct?: CachedEmailScalarFieldEnum | CachedEmailScalarFieldEnum[] + } + /** * StressfreiEmail without action */ @@ -16932,6 +17199,1174 @@ export namespace Prisma { } + /** + * Model CachedEmail + */ + + export type AggregateCachedEmail = { + _count: CachedEmailCountAggregateOutputType | null + _avg: CachedEmailAvgAggregateOutputType | null + _sum: CachedEmailSumAggregateOutputType | null + _min: CachedEmailMinAggregateOutputType | null + _max: CachedEmailMaxAggregateOutputType | null + } + + export type CachedEmailAvgAggregateOutputType = { + id: number | null + stressfreiEmailId: number | null + uid: number | null + contractId: number | null + assignedBy: number | null + } + + export type CachedEmailSumAggregateOutputType = { + id: number | null + stressfreiEmailId: number | null + uid: number | null + contractId: number | null + assignedBy: number | null + } + + export type CachedEmailMinAggregateOutputType = { + id: number | null + stressfreiEmailId: number | null + folder: $Enums.EmailFolder | null + messageId: string | null + uid: number | null + subject: string | null + fromAddress: string | null + fromName: string | null + toAddresses: string | null + ccAddresses: string | null + receivedAt: Date | null + textBody: string | null + htmlBody: string | null + hasAttachments: boolean | null + attachmentNames: string | null + contractId: number | null + assignedAt: Date | null + assignedBy: number | null + isAutoAssigned: boolean | null + isRead: boolean | null + isStarred: boolean | null + isDeleted: boolean | null + deletedAt: Date | null + createdAt: Date | null + updatedAt: Date | null + } + + export type CachedEmailMaxAggregateOutputType = { + id: number | null + stressfreiEmailId: number | null + folder: $Enums.EmailFolder | null + messageId: string | null + uid: number | null + subject: string | null + fromAddress: string | null + fromName: string | null + toAddresses: string | null + ccAddresses: string | null + receivedAt: Date | null + textBody: string | null + htmlBody: string | null + hasAttachments: boolean | null + attachmentNames: string | null + contractId: number | null + assignedAt: Date | null + assignedBy: number | null + isAutoAssigned: boolean | null + isRead: boolean | null + isStarred: boolean | null + isDeleted: boolean | null + deletedAt: Date | null + createdAt: Date | null + updatedAt: Date | null + } + + export type CachedEmailCountAggregateOutputType = { + id: number + stressfreiEmailId: number + folder: number + messageId: number + uid: number + subject: number + fromAddress: number + fromName: number + toAddresses: number + ccAddresses: number + receivedAt: number + textBody: number + htmlBody: number + hasAttachments: number + attachmentNames: number + contractId: number + assignedAt: number + assignedBy: number + isAutoAssigned: number + isRead: number + isStarred: number + isDeleted: number + deletedAt: number + createdAt: number + updatedAt: number + _all: number + } + + + export type CachedEmailAvgAggregateInputType = { + id?: true + stressfreiEmailId?: true + uid?: true + contractId?: true + assignedBy?: true + } + + export type CachedEmailSumAggregateInputType = { + id?: true + stressfreiEmailId?: true + uid?: true + contractId?: true + assignedBy?: true + } + + export type CachedEmailMinAggregateInputType = { + id?: true + stressfreiEmailId?: true + folder?: true + messageId?: true + uid?: true + subject?: true + fromAddress?: true + fromName?: true + toAddresses?: true + ccAddresses?: true + receivedAt?: true + textBody?: true + htmlBody?: true + hasAttachments?: true + attachmentNames?: true + contractId?: true + assignedAt?: true + assignedBy?: true + isAutoAssigned?: true + isRead?: true + isStarred?: true + isDeleted?: true + deletedAt?: true + createdAt?: true + updatedAt?: true + } + + export type CachedEmailMaxAggregateInputType = { + id?: true + stressfreiEmailId?: true + folder?: true + messageId?: true + uid?: true + subject?: true + fromAddress?: true + fromName?: true + toAddresses?: true + ccAddresses?: true + receivedAt?: true + textBody?: true + htmlBody?: true + hasAttachments?: true + attachmentNames?: true + contractId?: true + assignedAt?: true + assignedBy?: true + isAutoAssigned?: true + isRead?: true + isStarred?: true + isDeleted?: true + deletedAt?: true + createdAt?: true + updatedAt?: true + } + + export type CachedEmailCountAggregateInputType = { + id?: true + stressfreiEmailId?: true + folder?: true + messageId?: true + uid?: true + subject?: true + fromAddress?: true + fromName?: true + toAddresses?: true + ccAddresses?: true + receivedAt?: true + textBody?: true + htmlBody?: true + hasAttachments?: true + attachmentNames?: true + contractId?: true + assignedAt?: true + assignedBy?: true + isAutoAssigned?: true + isRead?: true + isStarred?: true + isDeleted?: true + deletedAt?: true + createdAt?: true + updatedAt?: true + _all?: true + } + + export type CachedEmailAggregateArgs = { + /** + * Filter which CachedEmail to aggregate. + */ + where?: CachedEmailWhereInput + /** + * {@link https://www.prisma.io/docs/concepts/components/prisma-client/sorting Sorting Docs} + * + * Determine the order of CachedEmails to fetch. + */ + orderBy?: CachedEmailOrderByWithRelationInput | CachedEmailOrderByWithRelationInput[] + /** + * {@link https://www.prisma.io/docs/concepts/components/prisma-client/pagination#cursor-based-pagination Cursor Docs} + * + * Sets the start position + */ + cursor?: CachedEmailWhereUniqueInput + /** + * {@link https://www.prisma.io/docs/concepts/components/prisma-client/pagination Pagination Docs} + * + * Take `±n` CachedEmails from the position of the cursor. + */ + take?: number + /** + * {@link https://www.prisma.io/docs/concepts/components/prisma-client/pagination Pagination Docs} + * + * Skip the first `n` CachedEmails. + */ + skip?: number + /** + * {@link https://www.prisma.io/docs/concepts/components/prisma-client/aggregations Aggregation Docs} + * + * Count returned CachedEmails + **/ + _count?: true | CachedEmailCountAggregateInputType + /** + * {@link https://www.prisma.io/docs/concepts/components/prisma-client/aggregations Aggregation Docs} + * + * Select which fields to average + **/ + _avg?: CachedEmailAvgAggregateInputType + /** + * {@link https://www.prisma.io/docs/concepts/components/prisma-client/aggregations Aggregation Docs} + * + * Select which fields to sum + **/ + _sum?: CachedEmailSumAggregateInputType + /** + * {@link https://www.prisma.io/docs/concepts/components/prisma-client/aggregations Aggregation Docs} + * + * Select which fields to find the minimum value + **/ + _min?: CachedEmailMinAggregateInputType + /** + * {@link https://www.prisma.io/docs/concepts/components/prisma-client/aggregations Aggregation Docs} + * + * Select which fields to find the maximum value + **/ + _max?: CachedEmailMaxAggregateInputType + } + + export type GetCachedEmailAggregateType = { + [P in keyof T & keyof AggregateCachedEmail]: P extends '_count' | 'count' + ? T[P] extends true + ? number + : GetScalarType + : GetScalarType + } + + + + + export type CachedEmailGroupByArgs = { + where?: CachedEmailWhereInput + orderBy?: CachedEmailOrderByWithAggregationInput | CachedEmailOrderByWithAggregationInput[] + by: CachedEmailScalarFieldEnum[] | CachedEmailScalarFieldEnum + having?: CachedEmailScalarWhereWithAggregatesInput + take?: number + skip?: number + _count?: CachedEmailCountAggregateInputType | true + _avg?: CachedEmailAvgAggregateInputType + _sum?: CachedEmailSumAggregateInputType + _min?: CachedEmailMinAggregateInputType + _max?: CachedEmailMaxAggregateInputType + } + + export type CachedEmailGroupByOutputType = { + id: number + stressfreiEmailId: number + folder: $Enums.EmailFolder + messageId: string + uid: number + subject: string | null + fromAddress: string + fromName: string | null + toAddresses: string + ccAddresses: string | null + receivedAt: Date + textBody: string | null + htmlBody: string | null + hasAttachments: boolean + attachmentNames: string | null + contractId: number | null + assignedAt: Date | null + assignedBy: number | null + isAutoAssigned: boolean + isRead: boolean + isStarred: boolean + isDeleted: boolean + deletedAt: Date | null + createdAt: Date + updatedAt: Date + _count: CachedEmailCountAggregateOutputType | null + _avg: CachedEmailAvgAggregateOutputType | null + _sum: CachedEmailSumAggregateOutputType | null + _min: CachedEmailMinAggregateOutputType | null + _max: CachedEmailMaxAggregateOutputType | null + } + + type GetCachedEmailGroupByPayload = Prisma.PrismaPromise< + Array< + PickEnumerable & + { + [P in ((keyof T) & (keyof CachedEmailGroupByOutputType))]: P extends '_count' + ? T[P] extends boolean + ? number + : GetScalarType + : GetScalarType + } + > + > + + + export type CachedEmailSelect = $Extensions.GetSelect<{ + id?: boolean + stressfreiEmailId?: boolean + folder?: boolean + messageId?: boolean + uid?: boolean + subject?: boolean + fromAddress?: boolean + fromName?: boolean + toAddresses?: boolean + ccAddresses?: boolean + receivedAt?: boolean + textBody?: boolean + htmlBody?: boolean + hasAttachments?: boolean + attachmentNames?: boolean + contractId?: boolean + assignedAt?: boolean + assignedBy?: boolean + isAutoAssigned?: boolean + isRead?: boolean + isStarred?: boolean + isDeleted?: boolean + deletedAt?: boolean + createdAt?: boolean + updatedAt?: boolean + stressfreiEmail?: boolean | StressfreiEmailDefaultArgs + contract?: boolean | CachedEmail$contractArgs + }, ExtArgs["result"]["cachedEmail"]> + + + export type CachedEmailSelectScalar = { + id?: boolean + stressfreiEmailId?: boolean + folder?: boolean + messageId?: boolean + uid?: boolean + subject?: boolean + fromAddress?: boolean + fromName?: boolean + toAddresses?: boolean + ccAddresses?: boolean + receivedAt?: boolean + textBody?: boolean + htmlBody?: boolean + hasAttachments?: boolean + attachmentNames?: boolean + contractId?: boolean + assignedAt?: boolean + assignedBy?: boolean + isAutoAssigned?: boolean + isRead?: boolean + isStarred?: boolean + isDeleted?: boolean + deletedAt?: boolean + createdAt?: boolean + updatedAt?: boolean + } + + export type CachedEmailInclude = { + stressfreiEmail?: boolean | StressfreiEmailDefaultArgs + contract?: boolean | CachedEmail$contractArgs + } + + export type $CachedEmailPayload = { + name: "CachedEmail" + objects: { + stressfreiEmail: Prisma.$StressfreiEmailPayload + contract: Prisma.$ContractPayload | null + } + scalars: $Extensions.GetPayloadResult<{ + id: number + stressfreiEmailId: number + folder: $Enums.EmailFolder + messageId: string + uid: number + subject: string | null + fromAddress: string + fromName: string | null + toAddresses: string + ccAddresses: string | null + receivedAt: Date + textBody: string | null + htmlBody: string | null + hasAttachments: boolean + attachmentNames: string | null + contractId: number | null + assignedAt: Date | null + assignedBy: number | null + isAutoAssigned: boolean + isRead: boolean + isStarred: boolean + isDeleted: boolean + deletedAt: Date | null + createdAt: Date + updatedAt: Date + }, ExtArgs["result"]["cachedEmail"]> + composites: {} + } + + type CachedEmailGetPayload = $Result.GetResult + + type CachedEmailCountArgs = + Omit & { + select?: CachedEmailCountAggregateInputType | true + } + + export interface CachedEmailDelegate { + [K: symbol]: { types: Prisma.TypeMap['model']['CachedEmail'], meta: { name: 'CachedEmail' } } + /** + * Find zero or one CachedEmail that matches the filter. + * @param {CachedEmailFindUniqueArgs} args - Arguments to find a CachedEmail + * @example + * // Get one CachedEmail + * const cachedEmail = await prisma.cachedEmail.findUnique({ + * where: { + * // ... provide filter here + * } + * }) + */ + findUnique(args: SelectSubset>): Prisma__CachedEmailClient<$Result.GetResult, T, "findUnique"> | null, null, ExtArgs> + + /** + * Find one CachedEmail that matches the filter or throw an error with `error.code='P2025'` + * if no matches were found. + * @param {CachedEmailFindUniqueOrThrowArgs} args - Arguments to find a CachedEmail + * @example + * // Get one CachedEmail + * const cachedEmail = await prisma.cachedEmail.findUniqueOrThrow({ + * where: { + * // ... provide filter here + * } + * }) + */ + findUniqueOrThrow(args: SelectSubset>): Prisma__CachedEmailClient<$Result.GetResult, T, "findUniqueOrThrow">, never, ExtArgs> + + /** + * Find the first CachedEmail that matches the filter. + * Note, that providing `undefined` is treated as the value not being there. + * Read more here: https://pris.ly/d/null-undefined + * @param {CachedEmailFindFirstArgs} args - Arguments to find a CachedEmail + * @example + * // Get one CachedEmail + * const cachedEmail = await prisma.cachedEmail.findFirst({ + * where: { + * // ... provide filter here + * } + * }) + */ + findFirst(args?: SelectSubset>): Prisma__CachedEmailClient<$Result.GetResult, T, "findFirst"> | null, null, ExtArgs> + + /** + * Find the first CachedEmail that matches the filter or + * throw `PrismaKnownClientError` with `P2025` code if no matches were found. + * Note, that providing `undefined` is treated as the value not being there. + * Read more here: https://pris.ly/d/null-undefined + * @param {CachedEmailFindFirstOrThrowArgs} args - Arguments to find a CachedEmail + * @example + * // Get one CachedEmail + * const cachedEmail = await prisma.cachedEmail.findFirstOrThrow({ + * where: { + * // ... provide filter here + * } + * }) + */ + findFirstOrThrow(args?: SelectSubset>): Prisma__CachedEmailClient<$Result.GetResult, T, "findFirstOrThrow">, never, ExtArgs> + + /** + * Find zero or more CachedEmails that matches the filter. + * Note, that providing `undefined` is treated as the value not being there. + * Read more here: https://pris.ly/d/null-undefined + * @param {CachedEmailFindManyArgs} args - Arguments to filter and select certain fields only. + * @example + * // Get all CachedEmails + * const cachedEmails = await prisma.cachedEmail.findMany() + * + * // Get first 10 CachedEmails + * const cachedEmails = await prisma.cachedEmail.findMany({ take: 10 }) + * + * // Only select the `id` + * const cachedEmailWithIdOnly = await prisma.cachedEmail.findMany({ select: { id: true } }) + * + */ + findMany(args?: SelectSubset>): Prisma.PrismaPromise<$Result.GetResult, T, "findMany">> + + /** + * Create a CachedEmail. + * @param {CachedEmailCreateArgs} args - Arguments to create a CachedEmail. + * @example + * // Create one CachedEmail + * const CachedEmail = await prisma.cachedEmail.create({ + * data: { + * // ... data to create a CachedEmail + * } + * }) + * + */ + create(args: SelectSubset>): Prisma__CachedEmailClient<$Result.GetResult, T, "create">, never, ExtArgs> + + /** + * Create many CachedEmails. + * @param {CachedEmailCreateManyArgs} args - Arguments to create many CachedEmails. + * @example + * // Create many CachedEmails + * const cachedEmail = await prisma.cachedEmail.createMany({ + * data: [ + * // ... provide data here + * ] + * }) + * + */ + createMany(args?: SelectSubset>): Prisma.PrismaPromise + + /** + * Delete a CachedEmail. + * @param {CachedEmailDeleteArgs} args - Arguments to delete one CachedEmail. + * @example + * // Delete one CachedEmail + * const CachedEmail = await prisma.cachedEmail.delete({ + * where: { + * // ... filter to delete one CachedEmail + * } + * }) + * + */ + delete(args: SelectSubset>): Prisma__CachedEmailClient<$Result.GetResult, T, "delete">, never, ExtArgs> + + /** + * Update one CachedEmail. + * @param {CachedEmailUpdateArgs} args - Arguments to update one CachedEmail. + * @example + * // Update one CachedEmail + * const cachedEmail = await prisma.cachedEmail.update({ + * where: { + * // ... provide filter here + * }, + * data: { + * // ... provide data here + * } + * }) + * + */ + update(args: SelectSubset>): Prisma__CachedEmailClient<$Result.GetResult, T, "update">, never, ExtArgs> + + /** + * Delete zero or more CachedEmails. + * @param {CachedEmailDeleteManyArgs} args - Arguments to filter CachedEmails to delete. + * @example + * // Delete a few CachedEmails + * const { count } = await prisma.cachedEmail.deleteMany({ + * where: { + * // ... provide filter here + * } + * }) + * + */ + deleteMany(args?: SelectSubset>): Prisma.PrismaPromise + + /** + * Update zero or more CachedEmails. + * Note, that providing `undefined` is treated as the value not being there. + * Read more here: https://pris.ly/d/null-undefined + * @param {CachedEmailUpdateManyArgs} args - Arguments to update one or more rows. + * @example + * // Update many CachedEmails + * const cachedEmail = await prisma.cachedEmail.updateMany({ + * where: { + * // ... provide filter here + * }, + * data: { + * // ... provide data here + * } + * }) + * + */ + updateMany(args: SelectSubset>): Prisma.PrismaPromise + + /** + * Create or update one CachedEmail. + * @param {CachedEmailUpsertArgs} args - Arguments to update or create a CachedEmail. + * @example + * // Update or create a CachedEmail + * const cachedEmail = await prisma.cachedEmail.upsert({ + * create: { + * // ... data to create a CachedEmail + * }, + * update: { + * // ... in case it already exists, update + * }, + * where: { + * // ... the filter for the CachedEmail we want to update + * } + * }) + */ + upsert(args: SelectSubset>): Prisma__CachedEmailClient<$Result.GetResult, T, "upsert">, never, ExtArgs> + + + /** + * Count the number of CachedEmails. + * Note, that providing `undefined` is treated as the value not being there. + * Read more here: https://pris.ly/d/null-undefined + * @param {CachedEmailCountArgs} args - Arguments to filter CachedEmails to count. + * @example + * // Count the number of CachedEmails + * const count = await prisma.cachedEmail.count({ + * where: { + * // ... the filter for the CachedEmails we want to count + * } + * }) + **/ + count( + args?: Subset, + ): Prisma.PrismaPromise< + T extends $Utils.Record<'select', any> + ? T['select'] extends true + ? number + : GetScalarType + : number + > + + /** + * Allows you to perform aggregations operations on a CachedEmail. + * Note, that providing `undefined` is treated as the value not being there. + * Read more here: https://pris.ly/d/null-undefined + * @param {CachedEmailAggregateArgs} args - Select which aggregations you would like to apply and on what fields. + * @example + * // Ordered by age ascending + * // Where email contains prisma.io + * // Limited to the 10 users + * const aggregations = await prisma.user.aggregate({ + * _avg: { + * age: true, + * }, + * where: { + * email: { + * contains: "prisma.io", + * }, + * }, + * orderBy: { + * age: "asc", + * }, + * take: 10, + * }) + **/ + aggregate(args: Subset): Prisma.PrismaPromise> + + /** + * Group by CachedEmail. + * Note, that providing `undefined` is treated as the value not being there. + * Read more here: https://pris.ly/d/null-undefined + * @param {CachedEmailGroupByArgs} args - Group by arguments. + * @example + * // Group by city, order by createdAt, get count + * const result = await prisma.user.groupBy({ + * by: ['city', 'createdAt'], + * orderBy: { + * createdAt: true + * }, + * _count: { + * _all: true + * }, + * }) + * + **/ + groupBy< + T extends CachedEmailGroupByArgs, + HasSelectOrTake extends Or< + Extends<'skip', Keys>, + Extends<'take', Keys> + >, + OrderByArg extends True extends HasSelectOrTake + ? { orderBy: CachedEmailGroupByArgs['orderBy'] } + : { orderBy?: CachedEmailGroupByArgs['orderBy'] }, + OrderFields extends ExcludeUnderscoreKeys>>, + ByFields extends MaybeTupleToUnion, + ByValid extends Has, + HavingFields extends GetHavingFields, + HavingValid extends Has, + ByEmpty extends T['by'] extends never[] ? True : False, + InputErrors extends ByEmpty extends True + ? `Error: "by" must not be empty.` + : HavingValid extends False + ? { + [P in HavingFields]: P extends ByFields + ? never + : P extends string + ? `Error: Field "${P}" used in "having" needs to be provided in "by".` + : [ + Error, + 'Field ', + P, + ` in "having" needs to be provided in "by"`, + ] + }[HavingFields] + : 'take' extends Keys + ? 'orderBy' extends Keys + ? ByValid extends True + ? {} + : { + [P in OrderFields]: P extends ByFields + ? never + : `Error: Field "${P}" in "orderBy" needs to be provided in "by"` + }[OrderFields] + : 'Error: If you provide "take", you also need to provide "orderBy"' + : 'skip' extends Keys + ? 'orderBy' extends Keys + ? ByValid extends True + ? {} + : { + [P in OrderFields]: P extends ByFields + ? never + : `Error: Field "${P}" in "orderBy" needs to be provided in "by"` + }[OrderFields] + : 'Error: If you provide "skip", you also need to provide "orderBy"' + : ByValid extends True + ? {} + : { + [P in OrderFields]: P extends ByFields + ? never + : `Error: Field "${P}" in "orderBy" needs to be provided in "by"` + }[OrderFields] + >(args: SubsetIntersection & InputErrors): {} extends InputErrors ? GetCachedEmailGroupByPayload : Prisma.PrismaPromise + /** + * Fields of the CachedEmail model + */ + readonly fields: CachedEmailFieldRefs; + } + + /** + * The delegate class that acts as a "Promise-like" for CachedEmail. + * Why is this prefixed with `Prisma__`? + * Because we want to prevent naming conflicts as mentioned in + * https://github.com/prisma/prisma-client-js/issues/707 + */ + export interface Prisma__CachedEmailClient extends Prisma.PrismaPromise { + readonly [Symbol.toStringTag]: "PrismaPromise" + stressfreiEmail = {}>(args?: Subset>): Prisma__StressfreiEmailClient<$Result.GetResult, T, "findUniqueOrThrow"> | Null, Null, ExtArgs> + contract = {}>(args?: Subset>): Prisma__ContractClient<$Result.GetResult, T, "findUniqueOrThrow"> | null, null, ExtArgs> + /** + * Attaches callbacks for the resolution and/or rejection of the Promise. + * @param onfulfilled The callback to execute when the Promise is resolved. + * @param onrejected The callback to execute when the Promise is rejected. + * @returns A Promise for the completion of which ever callback is executed. + */ + then(onfulfilled?: ((value: T) => TResult1 | PromiseLike) | undefined | null, onrejected?: ((reason: any) => TResult2 | PromiseLike) | undefined | null): $Utils.JsPromise + /** + * Attaches a callback for only the rejection of the Promise. + * @param onrejected The callback to execute when the Promise is rejected. + * @returns A Promise for the completion of the callback. + */ + catch(onrejected?: ((reason: any) => TResult | PromiseLike) | undefined | null): $Utils.JsPromise + /** + * Attaches a callback that is invoked when the Promise is settled (fulfilled or rejected). The + * resolved value cannot be modified from the callback. + * @param onfinally The callback to execute when the Promise is settled (fulfilled or rejected). + * @returns A Promise for the completion of the callback. + */ + finally(onfinally?: (() => void) | undefined | null): $Utils.JsPromise + } + + + + + /** + * Fields of the CachedEmail model + */ + interface CachedEmailFieldRefs { + readonly id: FieldRef<"CachedEmail", 'Int'> + readonly stressfreiEmailId: FieldRef<"CachedEmail", 'Int'> + readonly folder: FieldRef<"CachedEmail", 'EmailFolder'> + readonly messageId: FieldRef<"CachedEmail", 'String'> + readonly uid: FieldRef<"CachedEmail", 'Int'> + readonly subject: FieldRef<"CachedEmail", 'String'> + readonly fromAddress: FieldRef<"CachedEmail", 'String'> + readonly fromName: FieldRef<"CachedEmail", 'String'> + readonly toAddresses: FieldRef<"CachedEmail", 'String'> + readonly ccAddresses: FieldRef<"CachedEmail", 'String'> + readonly receivedAt: FieldRef<"CachedEmail", 'DateTime'> + readonly textBody: FieldRef<"CachedEmail", 'String'> + readonly htmlBody: FieldRef<"CachedEmail", 'String'> + readonly hasAttachments: FieldRef<"CachedEmail", 'Boolean'> + readonly attachmentNames: FieldRef<"CachedEmail", 'String'> + readonly contractId: FieldRef<"CachedEmail", 'Int'> + readonly assignedAt: FieldRef<"CachedEmail", 'DateTime'> + readonly assignedBy: FieldRef<"CachedEmail", 'Int'> + readonly isAutoAssigned: FieldRef<"CachedEmail", 'Boolean'> + readonly isRead: FieldRef<"CachedEmail", 'Boolean'> + readonly isStarred: FieldRef<"CachedEmail", 'Boolean'> + readonly isDeleted: FieldRef<"CachedEmail", 'Boolean'> + readonly deletedAt: FieldRef<"CachedEmail", 'DateTime'> + readonly createdAt: FieldRef<"CachedEmail", 'DateTime'> + readonly updatedAt: FieldRef<"CachedEmail", 'DateTime'> + } + + + // Custom InputTypes + /** + * CachedEmail findUnique + */ + export type CachedEmailFindUniqueArgs = { + /** + * Select specific fields to fetch from the CachedEmail + */ + select?: CachedEmailSelect | null + /** + * Choose, which related nodes to fetch as well + */ + include?: CachedEmailInclude | null + /** + * Filter, which CachedEmail to fetch. + */ + where: CachedEmailWhereUniqueInput + } + + /** + * CachedEmail findUniqueOrThrow + */ + export type CachedEmailFindUniqueOrThrowArgs = { + /** + * Select specific fields to fetch from the CachedEmail + */ + select?: CachedEmailSelect | null + /** + * Choose, which related nodes to fetch as well + */ + include?: CachedEmailInclude | null + /** + * Filter, which CachedEmail to fetch. + */ + where: CachedEmailWhereUniqueInput + } + + /** + * CachedEmail findFirst + */ + export type CachedEmailFindFirstArgs = { + /** + * Select specific fields to fetch from the CachedEmail + */ + select?: CachedEmailSelect | null + /** + * Choose, which related nodes to fetch as well + */ + include?: CachedEmailInclude | null + /** + * Filter, which CachedEmail to fetch. + */ + where?: CachedEmailWhereInput + /** + * {@link https://www.prisma.io/docs/concepts/components/prisma-client/sorting Sorting Docs} + * + * Determine the order of CachedEmails to fetch. + */ + orderBy?: CachedEmailOrderByWithRelationInput | CachedEmailOrderByWithRelationInput[] + /** + * {@link https://www.prisma.io/docs/concepts/components/prisma-client/pagination#cursor-based-pagination Cursor Docs} + * + * Sets the position for searching for CachedEmails. + */ + cursor?: CachedEmailWhereUniqueInput + /** + * {@link https://www.prisma.io/docs/concepts/components/prisma-client/pagination Pagination Docs} + * + * Take `±n` CachedEmails from the position of the cursor. + */ + take?: number + /** + * {@link https://www.prisma.io/docs/concepts/components/prisma-client/pagination Pagination Docs} + * + * Skip the first `n` CachedEmails. + */ + skip?: number + /** + * {@link https://www.prisma.io/docs/concepts/components/prisma-client/distinct Distinct Docs} + * + * Filter by unique combinations of CachedEmails. + */ + distinct?: CachedEmailScalarFieldEnum | CachedEmailScalarFieldEnum[] + } + + /** + * CachedEmail findFirstOrThrow + */ + export type CachedEmailFindFirstOrThrowArgs = { + /** + * Select specific fields to fetch from the CachedEmail + */ + select?: CachedEmailSelect | null + /** + * Choose, which related nodes to fetch as well + */ + include?: CachedEmailInclude | null + /** + * Filter, which CachedEmail to fetch. + */ + where?: CachedEmailWhereInput + /** + * {@link https://www.prisma.io/docs/concepts/components/prisma-client/sorting Sorting Docs} + * + * Determine the order of CachedEmails to fetch. + */ + orderBy?: CachedEmailOrderByWithRelationInput | CachedEmailOrderByWithRelationInput[] + /** + * {@link https://www.prisma.io/docs/concepts/components/prisma-client/pagination#cursor-based-pagination Cursor Docs} + * + * Sets the position for searching for CachedEmails. + */ + cursor?: CachedEmailWhereUniqueInput + /** + * {@link https://www.prisma.io/docs/concepts/components/prisma-client/pagination Pagination Docs} + * + * Take `±n` CachedEmails from the position of the cursor. + */ + take?: number + /** + * {@link https://www.prisma.io/docs/concepts/components/prisma-client/pagination Pagination Docs} + * + * Skip the first `n` CachedEmails. + */ + skip?: number + /** + * {@link https://www.prisma.io/docs/concepts/components/prisma-client/distinct Distinct Docs} + * + * Filter by unique combinations of CachedEmails. + */ + distinct?: CachedEmailScalarFieldEnum | CachedEmailScalarFieldEnum[] + } + + /** + * CachedEmail findMany + */ + export type CachedEmailFindManyArgs = { + /** + * Select specific fields to fetch from the CachedEmail + */ + select?: CachedEmailSelect | null + /** + * Choose, which related nodes to fetch as well + */ + include?: CachedEmailInclude | null + /** + * Filter, which CachedEmails to fetch. + */ + where?: CachedEmailWhereInput + /** + * {@link https://www.prisma.io/docs/concepts/components/prisma-client/sorting Sorting Docs} + * + * Determine the order of CachedEmails to fetch. + */ + orderBy?: CachedEmailOrderByWithRelationInput | CachedEmailOrderByWithRelationInput[] + /** + * {@link https://www.prisma.io/docs/concepts/components/prisma-client/pagination#cursor-based-pagination Cursor Docs} + * + * Sets the position for listing CachedEmails. + */ + cursor?: CachedEmailWhereUniqueInput + /** + * {@link https://www.prisma.io/docs/concepts/components/prisma-client/pagination Pagination Docs} + * + * Take `±n` CachedEmails from the position of the cursor. + */ + take?: number + /** + * {@link https://www.prisma.io/docs/concepts/components/prisma-client/pagination Pagination Docs} + * + * Skip the first `n` CachedEmails. + */ + skip?: number + distinct?: CachedEmailScalarFieldEnum | CachedEmailScalarFieldEnum[] + } + + /** + * CachedEmail create + */ + export type CachedEmailCreateArgs = { + /** + * Select specific fields to fetch from the CachedEmail + */ + select?: CachedEmailSelect | null + /** + * Choose, which related nodes to fetch as well + */ + include?: CachedEmailInclude | null + /** + * The data needed to create a CachedEmail. + */ + data: XOR + } + + /** + * CachedEmail createMany + */ + export type CachedEmailCreateManyArgs = { + /** + * The data used to create many CachedEmails. + */ + data: CachedEmailCreateManyInput | CachedEmailCreateManyInput[] + skipDuplicates?: boolean + } + + /** + * CachedEmail update + */ + export type CachedEmailUpdateArgs = { + /** + * Select specific fields to fetch from the CachedEmail + */ + select?: CachedEmailSelect | null + /** + * Choose, which related nodes to fetch as well + */ + include?: CachedEmailInclude | null + /** + * The data needed to update a CachedEmail. + */ + data: XOR + /** + * Choose, which CachedEmail to update. + */ + where: CachedEmailWhereUniqueInput + } + + /** + * CachedEmail updateMany + */ + export type CachedEmailUpdateManyArgs = { + /** + * The data used to update CachedEmails. + */ + data: XOR + /** + * Filter which CachedEmails to update + */ + where?: CachedEmailWhereInput + } + + /** + * CachedEmail upsert + */ + export type CachedEmailUpsertArgs = { + /** + * Select specific fields to fetch from the CachedEmail + */ + select?: CachedEmailSelect | null + /** + * Choose, which related nodes to fetch as well + */ + include?: CachedEmailInclude | null + /** + * The filter to search for the CachedEmail to update in case it exists. + */ + where: CachedEmailWhereUniqueInput + /** + * In case the CachedEmail found by the `where` argument doesn't exist, create a new CachedEmail with this data. + */ + create: XOR + /** + * In case the CachedEmail was found with the provided `where` argument, update it with this data. + */ + update: XOR + } + + /** + * CachedEmail delete + */ + export type CachedEmailDeleteArgs = { + /** + * Select specific fields to fetch from the CachedEmail + */ + select?: CachedEmailSelect | null + /** + * Choose, which related nodes to fetch as well + */ + include?: CachedEmailInclude | null + /** + * Filter which CachedEmail to delete. + */ + where: CachedEmailWhereUniqueInput + } + + /** + * CachedEmail deleteMany + */ + export type CachedEmailDeleteManyArgs = { + /** + * Filter which CachedEmails to delete + */ + where?: CachedEmailWhereInput + } + + /** + * CachedEmail.contract + */ + export type CachedEmail$contractArgs = { + /** + * Select specific fields to fetch from the Contract + */ + select?: ContractSelect | null + /** + * Choose, which related nodes to fetch as well + */ + include?: ContractInclude | null + where?: ContractWhereInput + } + + /** + * CachedEmail without action + */ + export type CachedEmailDefaultArgs = { + /** + * Select specific fields to fetch from the CachedEmail + */ + select?: CachedEmailSelect | null + /** + * Choose, which related nodes to fetch as well + */ + include?: CachedEmailInclude | null + } + + /** * Model Meter */ @@ -25167,6 +26602,7 @@ export namespace Prisma { tvDetails?: boolean | Contract$tvDetailsArgs carInsuranceDetails?: boolean | Contract$carInsuranceDetailsArgs tasks?: boolean | Contract$tasksArgs + assignedEmails?: boolean | Contract$assignedEmailsArgs _count?: boolean | ContractCountOutputTypeDefaultArgs }, ExtArgs["result"]["contract"]> @@ -25231,6 +26667,7 @@ export namespace Prisma { tvDetails?: boolean | Contract$tvDetailsArgs carInsuranceDetails?: boolean | Contract$carInsuranceDetailsArgs tasks?: boolean | Contract$tasksArgs + assignedEmails?: boolean | Contract$assignedEmailsArgs _count?: boolean | ContractCountOutputTypeDefaultArgs } @@ -25256,6 +26693,7 @@ export namespace Prisma { tvDetails: Prisma.$TvContractDetailsPayload | null carInsuranceDetails: Prisma.$CarInsuranceDetailsPayload | null tasks: Prisma.$ContractTaskPayload[] + assignedEmails: Prisma.$CachedEmailPayload[] } scalars: $Extensions.GetPayloadResult<{ id: number @@ -25654,6 +27092,7 @@ export namespace Prisma { tvDetails = {}>(args?: Subset>): Prisma__TvContractDetailsClient<$Result.GetResult, T, "findUniqueOrThrow"> | null, null, ExtArgs> carInsuranceDetails = {}>(args?: Subset>): Prisma__CarInsuranceDetailsClient<$Result.GetResult, T, "findUniqueOrThrow"> | null, null, ExtArgs> tasks = {}>(args?: Subset>): Prisma.PrismaPromise<$Result.GetResult, T, "findMany"> | Null> + assignedEmails = {}>(args?: Subset>): Prisma.PrismaPromise<$Result.GetResult, T, "findMany"> | Null> /** * Attaches callbacks for the resolution and/or rejection of the Promise. * @param onfulfilled The callback to execute when the Promise is resolved. @@ -26293,6 +27732,26 @@ export namespace Prisma { distinct?: ContractTaskScalarFieldEnum | ContractTaskScalarFieldEnum[] } + /** + * Contract.assignedEmails + */ + export type Contract$assignedEmailsArgs = { + /** + * Select specific fields to fetch from the CachedEmail + */ + select?: CachedEmailSelect | null + /** + * Choose, which related nodes to fetch as well + */ + include?: CachedEmailInclude | null + where?: CachedEmailWhereInput + orderBy?: CachedEmailOrderByWithRelationInput | CachedEmailOrderByWithRelationInput[] + cursor?: CachedEmailWhereUniqueInput + take?: number + skip?: number + distinct?: CachedEmailScalarFieldEnum | CachedEmailScalarFieldEnum[] + } + /** * Contract without action */ @@ -35167,6 +36626,7 @@ export namespace Prisma { firstName: 'firstName', lastName: 'lastName', isActive: 'isActive', + tokenInvalidatedAt: 'tokenInvalidatedAt', customerId: 'customerId', createdAt: 'createdAt', updatedAt: 'updatedAt' @@ -35319,6 +36779,13 @@ export namespace Prisma { passwordEncrypted: 'passwordEncrypted', domain: 'domain', defaultForwardEmail: 'defaultForwardEmail', + imapServer: 'imapServer', + imapPort: 'imapPort', + smtpServer: 'smtpServer', + smtpPort: 'smtpPort', + imapEncryption: 'imapEncryption', + smtpEncryption: 'smtpEncryption', + allowSelfSignedCerts: 'allowSelfSignedCerts', isActive: 'isActive', isDefault: 'isDefault', createdAt: 'createdAt', @@ -35338,6 +36805,8 @@ export namespace Prisma { isProvisioned: 'isProvisioned', provisionedAt: 'provisionedAt', provisionError: 'provisionError', + hasMailbox: 'hasMailbox', + emailPasswordEncrypted: 'emailPasswordEncrypted', createdAt: 'createdAt', updatedAt: 'updatedAt' }; @@ -35345,6 +36814,37 @@ export namespace Prisma { export type StressfreiEmailScalarFieldEnum = (typeof StressfreiEmailScalarFieldEnum)[keyof typeof StressfreiEmailScalarFieldEnum] + export const CachedEmailScalarFieldEnum: { + id: 'id', + stressfreiEmailId: 'stressfreiEmailId', + folder: 'folder', + messageId: 'messageId', + uid: 'uid', + subject: 'subject', + fromAddress: 'fromAddress', + fromName: 'fromName', + toAddresses: 'toAddresses', + ccAddresses: 'ccAddresses', + receivedAt: 'receivedAt', + textBody: 'textBody', + htmlBody: 'htmlBody', + hasAttachments: 'hasAttachments', + attachmentNames: 'attachmentNames', + contractId: 'contractId', + assignedAt: 'assignedAt', + assignedBy: 'assignedBy', + isAutoAssigned: 'isAutoAssigned', + isRead: 'isRead', + isStarred: 'isStarred', + isDeleted: 'isDeleted', + deletedAt: 'deletedAt', + createdAt: 'createdAt', + updatedAt: 'updatedAt' + }; + + export type CachedEmailScalarFieldEnum = (typeof CachedEmailScalarFieldEnum)[keyof typeof CachedEmailScalarFieldEnum] + + export const MeterScalarFieldEnum: { id: 'id', customerId: 'customerId', @@ -35707,6 +37207,20 @@ export namespace Prisma { + /** + * Reference to a field of type 'MailEncryption' + */ + export type EnumMailEncryptionFieldRefInput<$PrismaModel> = FieldRefInputType<$PrismaModel, 'MailEncryption'> + + + + /** + * Reference to a field of type 'EmailFolder' + */ + export type EnumEmailFolderFieldRefInput<$PrismaModel> = FieldRefInputType<$PrismaModel, 'EmailFolder'> + + + /** * Reference to a field of type 'MeterType' */ @@ -35816,6 +37330,7 @@ export namespace Prisma { firstName?: StringFilter<"User"> | string lastName?: StringFilter<"User"> | string isActive?: BoolFilter<"User"> | boolean + tokenInvalidatedAt?: DateTimeNullableFilter<"User"> | Date | string | null customerId?: IntNullableFilter<"User"> | number | null createdAt?: DateTimeFilter<"User"> | Date | string updatedAt?: DateTimeFilter<"User"> | Date | string @@ -35830,6 +37345,7 @@ export namespace Prisma { firstName?: SortOrder lastName?: SortOrder isActive?: SortOrder + tokenInvalidatedAt?: SortOrderInput | SortOrder customerId?: SortOrderInput | SortOrder createdAt?: SortOrder updatedAt?: SortOrder @@ -35848,6 +37364,7 @@ export namespace Prisma { firstName?: StringFilter<"User"> | string lastName?: StringFilter<"User"> | string isActive?: BoolFilter<"User"> | boolean + tokenInvalidatedAt?: DateTimeNullableFilter<"User"> | Date | string | null createdAt?: DateTimeFilter<"User"> | Date | string updatedAt?: DateTimeFilter<"User"> | Date | string customer?: XOR | null @@ -35861,6 +37378,7 @@ export namespace Prisma { firstName?: SortOrder lastName?: SortOrder isActive?: SortOrder + tokenInvalidatedAt?: SortOrderInput | SortOrder customerId?: SortOrderInput | SortOrder createdAt?: SortOrder updatedAt?: SortOrder @@ -35881,6 +37399,7 @@ export namespace Prisma { firstName?: StringWithAggregatesFilter<"User"> | string lastName?: StringWithAggregatesFilter<"User"> | string isActive?: BoolWithAggregatesFilter<"User"> | boolean + tokenInvalidatedAt?: DateTimeNullableWithAggregatesFilter<"User"> | Date | string | null customerId?: IntNullableWithAggregatesFilter<"User"> | number | null createdAt?: DateTimeWithAggregatesFilter<"User"> | Date | string updatedAt?: DateTimeWithAggregatesFilter<"User"> | Date | string @@ -36636,6 +38155,13 @@ export namespace Prisma { passwordEncrypted?: StringNullableFilter<"EmailProviderConfig"> | string | null domain?: StringFilter<"EmailProviderConfig"> | string defaultForwardEmail?: StringNullableFilter<"EmailProviderConfig"> | string | null + imapServer?: StringNullableFilter<"EmailProviderConfig"> | string | null + imapPort?: IntNullableFilter<"EmailProviderConfig"> | number | null + smtpServer?: StringNullableFilter<"EmailProviderConfig"> | string | null + smtpPort?: IntNullableFilter<"EmailProviderConfig"> | number | null + imapEncryption?: EnumMailEncryptionFilter<"EmailProviderConfig"> | $Enums.MailEncryption + smtpEncryption?: EnumMailEncryptionFilter<"EmailProviderConfig"> | $Enums.MailEncryption + allowSelfSignedCerts?: BoolFilter<"EmailProviderConfig"> | boolean isActive?: BoolFilter<"EmailProviderConfig"> | boolean isDefault?: BoolFilter<"EmailProviderConfig"> | boolean createdAt?: DateTimeFilter<"EmailProviderConfig"> | Date | string @@ -36652,6 +38178,13 @@ export namespace Prisma { passwordEncrypted?: SortOrderInput | SortOrder domain?: SortOrder defaultForwardEmail?: SortOrderInput | SortOrder + imapServer?: SortOrderInput | SortOrder + imapPort?: SortOrderInput | SortOrder + smtpServer?: SortOrderInput | SortOrder + smtpPort?: SortOrderInput | SortOrder + imapEncryption?: SortOrder + smtpEncryption?: SortOrder + allowSelfSignedCerts?: SortOrder isActive?: SortOrder isDefault?: SortOrder createdAt?: SortOrder @@ -36671,6 +38204,13 @@ export namespace Prisma { passwordEncrypted?: StringNullableFilter<"EmailProviderConfig"> | string | null domain?: StringFilter<"EmailProviderConfig"> | string defaultForwardEmail?: StringNullableFilter<"EmailProviderConfig"> | string | null + imapServer?: StringNullableFilter<"EmailProviderConfig"> | string | null + imapPort?: IntNullableFilter<"EmailProviderConfig"> | number | null + smtpServer?: StringNullableFilter<"EmailProviderConfig"> | string | null + smtpPort?: IntNullableFilter<"EmailProviderConfig"> | number | null + imapEncryption?: EnumMailEncryptionFilter<"EmailProviderConfig"> | $Enums.MailEncryption + smtpEncryption?: EnumMailEncryptionFilter<"EmailProviderConfig"> | $Enums.MailEncryption + allowSelfSignedCerts?: BoolFilter<"EmailProviderConfig"> | boolean isActive?: BoolFilter<"EmailProviderConfig"> | boolean isDefault?: BoolFilter<"EmailProviderConfig"> | boolean createdAt?: DateTimeFilter<"EmailProviderConfig"> | Date | string @@ -36687,6 +38227,13 @@ export namespace Prisma { passwordEncrypted?: SortOrderInput | SortOrder domain?: SortOrder defaultForwardEmail?: SortOrderInput | SortOrder + imapServer?: SortOrderInput | SortOrder + imapPort?: SortOrderInput | SortOrder + smtpServer?: SortOrderInput | SortOrder + smtpPort?: SortOrderInput | SortOrder + imapEncryption?: SortOrder + smtpEncryption?: SortOrder + allowSelfSignedCerts?: SortOrder isActive?: SortOrder isDefault?: SortOrder createdAt?: SortOrder @@ -36711,6 +38258,13 @@ export namespace Prisma { passwordEncrypted?: StringNullableWithAggregatesFilter<"EmailProviderConfig"> | string | null domain?: StringWithAggregatesFilter<"EmailProviderConfig"> | string defaultForwardEmail?: StringNullableWithAggregatesFilter<"EmailProviderConfig"> | string | null + imapServer?: StringNullableWithAggregatesFilter<"EmailProviderConfig"> | string | null + imapPort?: IntNullableWithAggregatesFilter<"EmailProviderConfig"> | number | null + smtpServer?: StringNullableWithAggregatesFilter<"EmailProviderConfig"> | string | null + smtpPort?: IntNullableWithAggregatesFilter<"EmailProviderConfig"> | number | null + imapEncryption?: EnumMailEncryptionWithAggregatesFilter<"EmailProviderConfig"> | $Enums.MailEncryption + smtpEncryption?: EnumMailEncryptionWithAggregatesFilter<"EmailProviderConfig"> | $Enums.MailEncryption + allowSelfSignedCerts?: BoolWithAggregatesFilter<"EmailProviderConfig"> | boolean isActive?: BoolWithAggregatesFilter<"EmailProviderConfig"> | boolean isDefault?: BoolWithAggregatesFilter<"EmailProviderConfig"> | boolean createdAt?: DateTimeWithAggregatesFilter<"EmailProviderConfig"> | Date | string @@ -36730,10 +38284,13 @@ export namespace Prisma { isProvisioned?: BoolFilter<"StressfreiEmail"> | boolean provisionedAt?: DateTimeNullableFilter<"StressfreiEmail"> | Date | string | null provisionError?: StringNullableFilter<"StressfreiEmail"> | string | null + hasMailbox?: BoolFilter<"StressfreiEmail"> | boolean + emailPasswordEncrypted?: StringNullableFilter<"StressfreiEmail"> | string | null createdAt?: DateTimeFilter<"StressfreiEmail"> | Date | string updatedAt?: DateTimeFilter<"StressfreiEmail"> | Date | string customer?: XOR contracts?: ContractListRelationFilter + cachedEmails?: CachedEmailListRelationFilter } export type StressfreiEmailOrderByWithRelationInput = { @@ -36746,10 +38303,13 @@ export namespace Prisma { isProvisioned?: SortOrder provisionedAt?: SortOrderInput | SortOrder provisionError?: SortOrderInput | SortOrder + hasMailbox?: SortOrder + emailPasswordEncrypted?: SortOrderInput | SortOrder createdAt?: SortOrder updatedAt?: SortOrder customer?: CustomerOrderByWithRelationInput contracts?: ContractOrderByRelationAggregateInput + cachedEmails?: CachedEmailOrderByRelationAggregateInput } export type StressfreiEmailWhereUniqueInput = Prisma.AtLeast<{ @@ -36765,10 +38325,13 @@ export namespace Prisma { isProvisioned?: BoolFilter<"StressfreiEmail"> | boolean provisionedAt?: DateTimeNullableFilter<"StressfreiEmail"> | Date | string | null provisionError?: StringNullableFilter<"StressfreiEmail"> | string | null + hasMailbox?: BoolFilter<"StressfreiEmail"> | boolean + emailPasswordEncrypted?: StringNullableFilter<"StressfreiEmail"> | string | null createdAt?: DateTimeFilter<"StressfreiEmail"> | Date | string updatedAt?: DateTimeFilter<"StressfreiEmail"> | Date | string customer?: XOR contracts?: ContractListRelationFilter + cachedEmails?: CachedEmailListRelationFilter }, "id"> export type StressfreiEmailOrderByWithAggregationInput = { @@ -36781,6 +38344,8 @@ export namespace Prisma { isProvisioned?: SortOrder provisionedAt?: SortOrderInput | SortOrder provisionError?: SortOrderInput | SortOrder + hasMailbox?: SortOrder + emailPasswordEncrypted?: SortOrderInput | SortOrder createdAt?: SortOrder updatedAt?: SortOrder _count?: StressfreiEmailCountOrderByAggregateInput @@ -36803,10 +38368,173 @@ export namespace Prisma { isProvisioned?: BoolWithAggregatesFilter<"StressfreiEmail"> | boolean provisionedAt?: DateTimeNullableWithAggregatesFilter<"StressfreiEmail"> | Date | string | null provisionError?: StringNullableWithAggregatesFilter<"StressfreiEmail"> | string | null + hasMailbox?: BoolWithAggregatesFilter<"StressfreiEmail"> | boolean + emailPasswordEncrypted?: StringNullableWithAggregatesFilter<"StressfreiEmail"> | string | null createdAt?: DateTimeWithAggregatesFilter<"StressfreiEmail"> | Date | string updatedAt?: DateTimeWithAggregatesFilter<"StressfreiEmail"> | Date | string } + export type CachedEmailWhereInput = { + AND?: CachedEmailWhereInput | CachedEmailWhereInput[] + OR?: CachedEmailWhereInput[] + NOT?: CachedEmailWhereInput | CachedEmailWhereInput[] + id?: IntFilter<"CachedEmail"> | number + stressfreiEmailId?: IntFilter<"CachedEmail"> | number + folder?: EnumEmailFolderFilter<"CachedEmail"> | $Enums.EmailFolder + messageId?: StringFilter<"CachedEmail"> | string + uid?: IntFilter<"CachedEmail"> | number + subject?: StringNullableFilter<"CachedEmail"> | string | null + fromAddress?: StringFilter<"CachedEmail"> | string + fromName?: StringNullableFilter<"CachedEmail"> | string | null + toAddresses?: StringFilter<"CachedEmail"> | string + ccAddresses?: StringNullableFilter<"CachedEmail"> | string | null + receivedAt?: DateTimeFilter<"CachedEmail"> | Date | string + textBody?: StringNullableFilter<"CachedEmail"> | string | null + htmlBody?: StringNullableFilter<"CachedEmail"> | string | null + hasAttachments?: BoolFilter<"CachedEmail"> | boolean + attachmentNames?: StringNullableFilter<"CachedEmail"> | string | null + contractId?: IntNullableFilter<"CachedEmail"> | number | null + assignedAt?: DateTimeNullableFilter<"CachedEmail"> | Date | string | null + assignedBy?: IntNullableFilter<"CachedEmail"> | number | null + isAutoAssigned?: BoolFilter<"CachedEmail"> | boolean + isRead?: BoolFilter<"CachedEmail"> | boolean + isStarred?: BoolFilter<"CachedEmail"> | boolean + isDeleted?: BoolFilter<"CachedEmail"> | boolean + deletedAt?: DateTimeNullableFilter<"CachedEmail"> | Date | string | null + createdAt?: DateTimeFilter<"CachedEmail"> | Date | string + updatedAt?: DateTimeFilter<"CachedEmail"> | Date | string + stressfreiEmail?: XOR + contract?: XOR | null + } + + export type CachedEmailOrderByWithRelationInput = { + id?: SortOrder + stressfreiEmailId?: SortOrder + folder?: SortOrder + messageId?: SortOrder + uid?: SortOrder + subject?: SortOrderInput | SortOrder + fromAddress?: SortOrder + fromName?: SortOrderInput | SortOrder + toAddresses?: SortOrder + ccAddresses?: SortOrderInput | SortOrder + receivedAt?: SortOrder + textBody?: SortOrderInput | SortOrder + htmlBody?: SortOrderInput | SortOrder + hasAttachments?: SortOrder + attachmentNames?: SortOrderInput | SortOrder + contractId?: SortOrderInput | SortOrder + assignedAt?: SortOrderInput | SortOrder + assignedBy?: SortOrderInput | SortOrder + isAutoAssigned?: SortOrder + isRead?: SortOrder + isStarred?: SortOrder + isDeleted?: SortOrder + deletedAt?: SortOrderInput | SortOrder + createdAt?: SortOrder + updatedAt?: SortOrder + stressfreiEmail?: StressfreiEmailOrderByWithRelationInput + contract?: ContractOrderByWithRelationInput + } + + export type CachedEmailWhereUniqueInput = Prisma.AtLeast<{ + id?: number + stressfreiEmailId_messageId_folder?: CachedEmailStressfreiEmailIdMessageIdFolderCompoundUniqueInput + AND?: CachedEmailWhereInput | CachedEmailWhereInput[] + OR?: CachedEmailWhereInput[] + NOT?: CachedEmailWhereInput | CachedEmailWhereInput[] + stressfreiEmailId?: IntFilter<"CachedEmail"> | number + folder?: EnumEmailFolderFilter<"CachedEmail"> | $Enums.EmailFolder + messageId?: StringFilter<"CachedEmail"> | string + uid?: IntFilter<"CachedEmail"> | number + subject?: StringNullableFilter<"CachedEmail"> | string | null + fromAddress?: StringFilter<"CachedEmail"> | string + fromName?: StringNullableFilter<"CachedEmail"> | string | null + toAddresses?: StringFilter<"CachedEmail"> | string + ccAddresses?: StringNullableFilter<"CachedEmail"> | string | null + receivedAt?: DateTimeFilter<"CachedEmail"> | Date | string + textBody?: StringNullableFilter<"CachedEmail"> | string | null + htmlBody?: StringNullableFilter<"CachedEmail"> | string | null + hasAttachments?: BoolFilter<"CachedEmail"> | boolean + attachmentNames?: StringNullableFilter<"CachedEmail"> | string | null + contractId?: IntNullableFilter<"CachedEmail"> | number | null + assignedAt?: DateTimeNullableFilter<"CachedEmail"> | Date | string | null + assignedBy?: IntNullableFilter<"CachedEmail"> | number | null + isAutoAssigned?: BoolFilter<"CachedEmail"> | boolean + isRead?: BoolFilter<"CachedEmail"> | boolean + isStarred?: BoolFilter<"CachedEmail"> | boolean + isDeleted?: BoolFilter<"CachedEmail"> | boolean + deletedAt?: DateTimeNullableFilter<"CachedEmail"> | Date | string | null + createdAt?: DateTimeFilter<"CachedEmail"> | Date | string + updatedAt?: DateTimeFilter<"CachedEmail"> | Date | string + stressfreiEmail?: XOR + contract?: XOR | null + }, "id" | "stressfreiEmailId_messageId_folder"> + + export type CachedEmailOrderByWithAggregationInput = { + id?: SortOrder + stressfreiEmailId?: SortOrder + folder?: SortOrder + messageId?: SortOrder + uid?: SortOrder + subject?: SortOrderInput | SortOrder + fromAddress?: SortOrder + fromName?: SortOrderInput | SortOrder + toAddresses?: SortOrder + ccAddresses?: SortOrderInput | SortOrder + receivedAt?: SortOrder + textBody?: SortOrderInput | SortOrder + htmlBody?: SortOrderInput | SortOrder + hasAttachments?: SortOrder + attachmentNames?: SortOrderInput | SortOrder + contractId?: SortOrderInput | SortOrder + assignedAt?: SortOrderInput | SortOrder + assignedBy?: SortOrderInput | SortOrder + isAutoAssigned?: SortOrder + isRead?: SortOrder + isStarred?: SortOrder + isDeleted?: SortOrder + deletedAt?: SortOrderInput | SortOrder + createdAt?: SortOrder + updatedAt?: SortOrder + _count?: CachedEmailCountOrderByAggregateInput + _avg?: CachedEmailAvgOrderByAggregateInput + _max?: CachedEmailMaxOrderByAggregateInput + _min?: CachedEmailMinOrderByAggregateInput + _sum?: CachedEmailSumOrderByAggregateInput + } + + export type CachedEmailScalarWhereWithAggregatesInput = { + AND?: CachedEmailScalarWhereWithAggregatesInput | CachedEmailScalarWhereWithAggregatesInput[] + OR?: CachedEmailScalarWhereWithAggregatesInput[] + NOT?: CachedEmailScalarWhereWithAggregatesInput | CachedEmailScalarWhereWithAggregatesInput[] + id?: IntWithAggregatesFilter<"CachedEmail"> | number + stressfreiEmailId?: IntWithAggregatesFilter<"CachedEmail"> | number + folder?: EnumEmailFolderWithAggregatesFilter<"CachedEmail"> | $Enums.EmailFolder + messageId?: StringWithAggregatesFilter<"CachedEmail"> | string + uid?: IntWithAggregatesFilter<"CachedEmail"> | number + subject?: StringNullableWithAggregatesFilter<"CachedEmail"> | string | null + fromAddress?: StringWithAggregatesFilter<"CachedEmail"> | string + fromName?: StringNullableWithAggregatesFilter<"CachedEmail"> | string | null + toAddresses?: StringWithAggregatesFilter<"CachedEmail"> | string + ccAddresses?: StringNullableWithAggregatesFilter<"CachedEmail"> | string | null + receivedAt?: DateTimeWithAggregatesFilter<"CachedEmail"> | Date | string + textBody?: StringNullableWithAggregatesFilter<"CachedEmail"> | string | null + htmlBody?: StringNullableWithAggregatesFilter<"CachedEmail"> | string | null + hasAttachments?: BoolWithAggregatesFilter<"CachedEmail"> | boolean + attachmentNames?: StringNullableWithAggregatesFilter<"CachedEmail"> | string | null + contractId?: IntNullableWithAggregatesFilter<"CachedEmail"> | number | null + assignedAt?: DateTimeNullableWithAggregatesFilter<"CachedEmail"> | Date | string | null + assignedBy?: IntNullableWithAggregatesFilter<"CachedEmail"> | number | null + isAutoAssigned?: BoolWithAggregatesFilter<"CachedEmail"> | boolean + isRead?: BoolWithAggregatesFilter<"CachedEmail"> | boolean + isStarred?: BoolWithAggregatesFilter<"CachedEmail"> | boolean + isDeleted?: BoolWithAggregatesFilter<"CachedEmail"> | boolean + deletedAt?: DateTimeNullableWithAggregatesFilter<"CachedEmail"> | Date | string | null + createdAt?: DateTimeWithAggregatesFilter<"CachedEmail"> | Date | string + updatedAt?: DateTimeWithAggregatesFilter<"CachedEmail"> | Date | string + } + export type MeterWhereInput = { AND?: MeterWhereInput | MeterWhereInput[] OR?: MeterWhereInput[] @@ -37416,6 +39144,7 @@ export namespace Prisma { tvDetails?: XOR | null carInsuranceDetails?: XOR | null tasks?: ContractTaskListRelationFilter + assignedEmails?: CachedEmailListRelationFilter } export type ContractOrderByWithRelationInput = { @@ -37475,6 +39204,7 @@ export namespace Prisma { tvDetails?: TvContractDetailsOrderByWithRelationInput carInsuranceDetails?: CarInsuranceDetailsOrderByWithRelationInput tasks?: ContractTaskOrderByRelationAggregateInput + assignedEmails?: CachedEmailOrderByRelationAggregateInput } export type ContractWhereUniqueInput = Prisma.AtLeast<{ @@ -37537,6 +39267,7 @@ export namespace Prisma { tvDetails?: XOR | null carInsuranceDetails?: XOR | null tasks?: ContractTaskListRelationFilter + assignedEmails?: CachedEmailListRelationFilter }, "id" | "contractNumber" | "previousContractId"> export type ContractOrderByWithAggregationInput = { @@ -38406,6 +40137,7 @@ export namespace Prisma { firstName: string lastName: string isActive?: boolean + tokenInvalidatedAt?: Date | string | null createdAt?: Date | string updatedAt?: Date | string customer?: CustomerCreateNestedOneWithoutUserInput @@ -38419,6 +40151,7 @@ export namespace Prisma { firstName: string lastName: string isActive?: boolean + tokenInvalidatedAt?: Date | string | null customerId?: number | null createdAt?: Date | string updatedAt?: Date | string @@ -38431,6 +40164,7 @@ export namespace Prisma { firstName?: StringFieldUpdateOperationsInput | string lastName?: StringFieldUpdateOperationsInput | string isActive?: BoolFieldUpdateOperationsInput | boolean + tokenInvalidatedAt?: NullableDateTimeFieldUpdateOperationsInput | Date | string | null createdAt?: DateTimeFieldUpdateOperationsInput | Date | string updatedAt?: DateTimeFieldUpdateOperationsInput | Date | string customer?: CustomerUpdateOneWithoutUserNestedInput @@ -38444,6 +40178,7 @@ export namespace Prisma { firstName?: StringFieldUpdateOperationsInput | string lastName?: StringFieldUpdateOperationsInput | string isActive?: BoolFieldUpdateOperationsInput | boolean + tokenInvalidatedAt?: NullableDateTimeFieldUpdateOperationsInput | Date | string | null customerId?: NullableIntFieldUpdateOperationsInput | number | null createdAt?: DateTimeFieldUpdateOperationsInput | Date | string updatedAt?: DateTimeFieldUpdateOperationsInput | Date | string @@ -38457,6 +40192,7 @@ export namespace Prisma { firstName: string lastName: string isActive?: boolean + tokenInvalidatedAt?: Date | string | null customerId?: number | null createdAt?: Date | string updatedAt?: Date | string @@ -38468,6 +40204,7 @@ export namespace Prisma { firstName?: StringFieldUpdateOperationsInput | string lastName?: StringFieldUpdateOperationsInput | string isActive?: BoolFieldUpdateOperationsInput | boolean + tokenInvalidatedAt?: NullableDateTimeFieldUpdateOperationsInput | Date | string | null createdAt?: DateTimeFieldUpdateOperationsInput | Date | string updatedAt?: DateTimeFieldUpdateOperationsInput | Date | string } @@ -38479,6 +40216,7 @@ export namespace Prisma { firstName?: StringFieldUpdateOperationsInput | string lastName?: StringFieldUpdateOperationsInput | string isActive?: BoolFieldUpdateOperationsInput | boolean + tokenInvalidatedAt?: NullableDateTimeFieldUpdateOperationsInput | Date | string | null customerId?: NullableIntFieldUpdateOperationsInput | number | null createdAt?: DateTimeFieldUpdateOperationsInput | Date | string updatedAt?: DateTimeFieldUpdateOperationsInput | Date | string @@ -39274,6 +41012,13 @@ export namespace Prisma { passwordEncrypted?: string | null domain: string defaultForwardEmail?: string | null + imapServer?: string | null + imapPort?: number | null + smtpServer?: string | null + smtpPort?: number | null + imapEncryption?: $Enums.MailEncryption + smtpEncryption?: $Enums.MailEncryption + allowSelfSignedCerts?: boolean isActive?: boolean isDefault?: boolean createdAt?: Date | string @@ -39290,6 +41035,13 @@ export namespace Prisma { passwordEncrypted?: string | null domain: string defaultForwardEmail?: string | null + imapServer?: string | null + imapPort?: number | null + smtpServer?: string | null + smtpPort?: number | null + imapEncryption?: $Enums.MailEncryption + smtpEncryption?: $Enums.MailEncryption + allowSelfSignedCerts?: boolean isActive?: boolean isDefault?: boolean createdAt?: Date | string @@ -39305,6 +41057,13 @@ export namespace Prisma { passwordEncrypted?: NullableStringFieldUpdateOperationsInput | string | null domain?: StringFieldUpdateOperationsInput | string defaultForwardEmail?: NullableStringFieldUpdateOperationsInput | string | null + imapServer?: NullableStringFieldUpdateOperationsInput | string | null + imapPort?: NullableIntFieldUpdateOperationsInput | number | null + smtpServer?: NullableStringFieldUpdateOperationsInput | string | null + smtpPort?: NullableIntFieldUpdateOperationsInput | number | null + imapEncryption?: EnumMailEncryptionFieldUpdateOperationsInput | $Enums.MailEncryption + smtpEncryption?: EnumMailEncryptionFieldUpdateOperationsInput | $Enums.MailEncryption + allowSelfSignedCerts?: BoolFieldUpdateOperationsInput | boolean isActive?: BoolFieldUpdateOperationsInput | boolean isDefault?: BoolFieldUpdateOperationsInput | boolean createdAt?: DateTimeFieldUpdateOperationsInput | Date | string @@ -39321,6 +41080,13 @@ export namespace Prisma { passwordEncrypted?: NullableStringFieldUpdateOperationsInput | string | null domain?: StringFieldUpdateOperationsInput | string defaultForwardEmail?: NullableStringFieldUpdateOperationsInput | string | null + imapServer?: NullableStringFieldUpdateOperationsInput | string | null + imapPort?: NullableIntFieldUpdateOperationsInput | number | null + smtpServer?: NullableStringFieldUpdateOperationsInput | string | null + smtpPort?: NullableIntFieldUpdateOperationsInput | number | null + imapEncryption?: EnumMailEncryptionFieldUpdateOperationsInput | $Enums.MailEncryption + smtpEncryption?: EnumMailEncryptionFieldUpdateOperationsInput | $Enums.MailEncryption + allowSelfSignedCerts?: BoolFieldUpdateOperationsInput | boolean isActive?: BoolFieldUpdateOperationsInput | boolean isDefault?: BoolFieldUpdateOperationsInput | boolean createdAt?: DateTimeFieldUpdateOperationsInput | Date | string @@ -39337,6 +41103,13 @@ export namespace Prisma { passwordEncrypted?: string | null domain: string defaultForwardEmail?: string | null + imapServer?: string | null + imapPort?: number | null + smtpServer?: string | null + smtpPort?: number | null + imapEncryption?: $Enums.MailEncryption + smtpEncryption?: $Enums.MailEncryption + allowSelfSignedCerts?: boolean isActive?: boolean isDefault?: boolean createdAt?: Date | string @@ -39352,6 +41125,13 @@ export namespace Prisma { passwordEncrypted?: NullableStringFieldUpdateOperationsInput | string | null domain?: StringFieldUpdateOperationsInput | string defaultForwardEmail?: NullableStringFieldUpdateOperationsInput | string | null + imapServer?: NullableStringFieldUpdateOperationsInput | string | null + imapPort?: NullableIntFieldUpdateOperationsInput | number | null + smtpServer?: NullableStringFieldUpdateOperationsInput | string | null + smtpPort?: NullableIntFieldUpdateOperationsInput | number | null + imapEncryption?: EnumMailEncryptionFieldUpdateOperationsInput | $Enums.MailEncryption + smtpEncryption?: EnumMailEncryptionFieldUpdateOperationsInput | $Enums.MailEncryption + allowSelfSignedCerts?: BoolFieldUpdateOperationsInput | boolean isActive?: BoolFieldUpdateOperationsInput | boolean isDefault?: BoolFieldUpdateOperationsInput | boolean createdAt?: DateTimeFieldUpdateOperationsInput | Date | string @@ -39368,6 +41148,13 @@ export namespace Prisma { passwordEncrypted?: NullableStringFieldUpdateOperationsInput | string | null domain?: StringFieldUpdateOperationsInput | string defaultForwardEmail?: NullableStringFieldUpdateOperationsInput | string | null + imapServer?: NullableStringFieldUpdateOperationsInput | string | null + imapPort?: NullableIntFieldUpdateOperationsInput | number | null + smtpServer?: NullableStringFieldUpdateOperationsInput | string | null + smtpPort?: NullableIntFieldUpdateOperationsInput | number | null + imapEncryption?: EnumMailEncryptionFieldUpdateOperationsInput | $Enums.MailEncryption + smtpEncryption?: EnumMailEncryptionFieldUpdateOperationsInput | $Enums.MailEncryption + allowSelfSignedCerts?: BoolFieldUpdateOperationsInput | boolean isActive?: BoolFieldUpdateOperationsInput | boolean isDefault?: BoolFieldUpdateOperationsInput | boolean createdAt?: DateTimeFieldUpdateOperationsInput | Date | string @@ -39382,10 +41169,13 @@ export namespace Prisma { isProvisioned?: boolean provisionedAt?: Date | string | null provisionError?: string | null + hasMailbox?: boolean + emailPasswordEncrypted?: string | null createdAt?: Date | string updatedAt?: Date | string customer: CustomerCreateNestedOneWithoutStressfreiEmailsInput contracts?: ContractCreateNestedManyWithoutStressfreiEmailInput + cachedEmails?: CachedEmailCreateNestedManyWithoutStressfreiEmailInput } export type StressfreiEmailUncheckedCreateInput = { @@ -39398,9 +41188,12 @@ export namespace Prisma { isProvisioned?: boolean provisionedAt?: Date | string | null provisionError?: string | null + hasMailbox?: boolean + emailPasswordEncrypted?: string | null createdAt?: Date | string updatedAt?: Date | string contracts?: ContractUncheckedCreateNestedManyWithoutStressfreiEmailInput + cachedEmails?: CachedEmailUncheckedCreateNestedManyWithoutStressfreiEmailInput } export type StressfreiEmailUpdateInput = { @@ -39411,10 +41204,13 @@ export namespace Prisma { isProvisioned?: BoolFieldUpdateOperationsInput | boolean provisionedAt?: NullableDateTimeFieldUpdateOperationsInput | Date | string | null provisionError?: NullableStringFieldUpdateOperationsInput | string | null + hasMailbox?: BoolFieldUpdateOperationsInput | boolean + emailPasswordEncrypted?: NullableStringFieldUpdateOperationsInput | string | null createdAt?: DateTimeFieldUpdateOperationsInput | Date | string updatedAt?: DateTimeFieldUpdateOperationsInput | Date | string customer?: CustomerUpdateOneRequiredWithoutStressfreiEmailsNestedInput contracts?: ContractUpdateManyWithoutStressfreiEmailNestedInput + cachedEmails?: CachedEmailUpdateManyWithoutStressfreiEmailNestedInput } export type StressfreiEmailUncheckedUpdateInput = { @@ -39427,9 +41223,12 @@ export namespace Prisma { isProvisioned?: BoolFieldUpdateOperationsInput | boolean provisionedAt?: NullableDateTimeFieldUpdateOperationsInput | Date | string | null provisionError?: NullableStringFieldUpdateOperationsInput | string | null + hasMailbox?: BoolFieldUpdateOperationsInput | boolean + emailPasswordEncrypted?: NullableStringFieldUpdateOperationsInput | string | null createdAt?: DateTimeFieldUpdateOperationsInput | Date | string updatedAt?: DateTimeFieldUpdateOperationsInput | Date | string contracts?: ContractUncheckedUpdateManyWithoutStressfreiEmailNestedInput + cachedEmails?: CachedEmailUncheckedUpdateManyWithoutStressfreiEmailNestedInput } export type StressfreiEmailCreateManyInput = { @@ -39442,6 +41241,8 @@ export namespace Prisma { isProvisioned?: boolean provisionedAt?: Date | string | null provisionError?: string | null + hasMailbox?: boolean + emailPasswordEncrypted?: string | null createdAt?: Date | string updatedAt?: Date | string } @@ -39454,6 +41255,8 @@ export namespace Prisma { isProvisioned?: BoolFieldUpdateOperationsInput | boolean provisionedAt?: NullableDateTimeFieldUpdateOperationsInput | Date | string | null provisionError?: NullableStringFieldUpdateOperationsInput | string | null + hasMailbox?: BoolFieldUpdateOperationsInput | boolean + emailPasswordEncrypted?: NullableStringFieldUpdateOperationsInput | string | null createdAt?: DateTimeFieldUpdateOperationsInput | Date | string updatedAt?: DateTimeFieldUpdateOperationsInput | Date | string } @@ -39468,6 +41271,199 @@ export namespace Prisma { isProvisioned?: BoolFieldUpdateOperationsInput | boolean provisionedAt?: NullableDateTimeFieldUpdateOperationsInput | Date | string | null provisionError?: NullableStringFieldUpdateOperationsInput | string | null + hasMailbox?: BoolFieldUpdateOperationsInput | boolean + emailPasswordEncrypted?: NullableStringFieldUpdateOperationsInput | string | null + createdAt?: DateTimeFieldUpdateOperationsInput | Date | string + updatedAt?: DateTimeFieldUpdateOperationsInput | Date | string + } + + export type CachedEmailCreateInput = { + folder?: $Enums.EmailFolder + messageId: string + uid: number + subject?: string | null + fromAddress: string + fromName?: string | null + toAddresses: string + ccAddresses?: string | null + receivedAt: Date | string + textBody?: string | null + htmlBody?: string | null + hasAttachments?: boolean + attachmentNames?: string | null + assignedAt?: Date | string | null + assignedBy?: number | null + isAutoAssigned?: boolean + isRead?: boolean + isStarred?: boolean + isDeleted?: boolean + deletedAt?: Date | string | null + createdAt?: Date | string + updatedAt?: Date | string + stressfreiEmail: StressfreiEmailCreateNestedOneWithoutCachedEmailsInput + contract?: ContractCreateNestedOneWithoutAssignedEmailsInput + } + + export type CachedEmailUncheckedCreateInput = { + id?: number + stressfreiEmailId: number + folder?: $Enums.EmailFolder + messageId: string + uid: number + subject?: string | null + fromAddress: string + fromName?: string | null + toAddresses: string + ccAddresses?: string | null + receivedAt: Date | string + textBody?: string | null + htmlBody?: string | null + hasAttachments?: boolean + attachmentNames?: string | null + contractId?: number | null + assignedAt?: Date | string | null + assignedBy?: number | null + isAutoAssigned?: boolean + isRead?: boolean + isStarred?: boolean + isDeleted?: boolean + deletedAt?: Date | string | null + createdAt?: Date | string + updatedAt?: Date | string + } + + export type CachedEmailUpdateInput = { + folder?: EnumEmailFolderFieldUpdateOperationsInput | $Enums.EmailFolder + messageId?: StringFieldUpdateOperationsInput | string + uid?: IntFieldUpdateOperationsInput | number + subject?: NullableStringFieldUpdateOperationsInput | string | null + fromAddress?: StringFieldUpdateOperationsInput | string + fromName?: NullableStringFieldUpdateOperationsInput | string | null + toAddresses?: StringFieldUpdateOperationsInput | string + ccAddresses?: NullableStringFieldUpdateOperationsInput | string | null + receivedAt?: DateTimeFieldUpdateOperationsInput | Date | string + textBody?: NullableStringFieldUpdateOperationsInput | string | null + htmlBody?: NullableStringFieldUpdateOperationsInput | string | null + hasAttachments?: BoolFieldUpdateOperationsInput | boolean + attachmentNames?: NullableStringFieldUpdateOperationsInput | string | null + assignedAt?: NullableDateTimeFieldUpdateOperationsInput | Date | string | null + assignedBy?: NullableIntFieldUpdateOperationsInput | number | null + isAutoAssigned?: BoolFieldUpdateOperationsInput | boolean + isRead?: BoolFieldUpdateOperationsInput | boolean + isStarred?: BoolFieldUpdateOperationsInput | boolean + isDeleted?: BoolFieldUpdateOperationsInput | boolean + deletedAt?: NullableDateTimeFieldUpdateOperationsInput | Date | string | null + createdAt?: DateTimeFieldUpdateOperationsInput | Date | string + updatedAt?: DateTimeFieldUpdateOperationsInput | Date | string + stressfreiEmail?: StressfreiEmailUpdateOneRequiredWithoutCachedEmailsNestedInput + contract?: ContractUpdateOneWithoutAssignedEmailsNestedInput + } + + export type CachedEmailUncheckedUpdateInput = { + id?: IntFieldUpdateOperationsInput | number + stressfreiEmailId?: IntFieldUpdateOperationsInput | number + folder?: EnumEmailFolderFieldUpdateOperationsInput | $Enums.EmailFolder + messageId?: StringFieldUpdateOperationsInput | string + uid?: IntFieldUpdateOperationsInput | number + subject?: NullableStringFieldUpdateOperationsInput | string | null + fromAddress?: StringFieldUpdateOperationsInput | string + fromName?: NullableStringFieldUpdateOperationsInput | string | null + toAddresses?: StringFieldUpdateOperationsInput | string + ccAddresses?: NullableStringFieldUpdateOperationsInput | string | null + receivedAt?: DateTimeFieldUpdateOperationsInput | Date | string + textBody?: NullableStringFieldUpdateOperationsInput | string | null + htmlBody?: NullableStringFieldUpdateOperationsInput | string | null + hasAttachments?: BoolFieldUpdateOperationsInput | boolean + attachmentNames?: NullableStringFieldUpdateOperationsInput | string | null + contractId?: NullableIntFieldUpdateOperationsInput | number | null + assignedAt?: NullableDateTimeFieldUpdateOperationsInput | Date | string | null + assignedBy?: NullableIntFieldUpdateOperationsInput | number | null + isAutoAssigned?: BoolFieldUpdateOperationsInput | boolean + isRead?: BoolFieldUpdateOperationsInput | boolean + isStarred?: BoolFieldUpdateOperationsInput | boolean + isDeleted?: BoolFieldUpdateOperationsInput | boolean + deletedAt?: NullableDateTimeFieldUpdateOperationsInput | Date | string | null + createdAt?: DateTimeFieldUpdateOperationsInput | Date | string + updatedAt?: DateTimeFieldUpdateOperationsInput | Date | string + } + + export type CachedEmailCreateManyInput = { + id?: number + stressfreiEmailId: number + folder?: $Enums.EmailFolder + messageId: string + uid: number + subject?: string | null + fromAddress: string + fromName?: string | null + toAddresses: string + ccAddresses?: string | null + receivedAt: Date | string + textBody?: string | null + htmlBody?: string | null + hasAttachments?: boolean + attachmentNames?: string | null + contractId?: number | null + assignedAt?: Date | string | null + assignedBy?: number | null + isAutoAssigned?: boolean + isRead?: boolean + isStarred?: boolean + isDeleted?: boolean + deletedAt?: Date | string | null + createdAt?: Date | string + updatedAt?: Date | string + } + + export type CachedEmailUpdateManyMutationInput = { + folder?: EnumEmailFolderFieldUpdateOperationsInput | $Enums.EmailFolder + messageId?: StringFieldUpdateOperationsInput | string + uid?: IntFieldUpdateOperationsInput | number + subject?: NullableStringFieldUpdateOperationsInput | string | null + fromAddress?: StringFieldUpdateOperationsInput | string + fromName?: NullableStringFieldUpdateOperationsInput | string | null + toAddresses?: StringFieldUpdateOperationsInput | string + ccAddresses?: NullableStringFieldUpdateOperationsInput | string | null + receivedAt?: DateTimeFieldUpdateOperationsInput | Date | string + textBody?: NullableStringFieldUpdateOperationsInput | string | null + htmlBody?: NullableStringFieldUpdateOperationsInput | string | null + hasAttachments?: BoolFieldUpdateOperationsInput | boolean + attachmentNames?: NullableStringFieldUpdateOperationsInput | string | null + assignedAt?: NullableDateTimeFieldUpdateOperationsInput | Date | string | null + assignedBy?: NullableIntFieldUpdateOperationsInput | number | null + isAutoAssigned?: BoolFieldUpdateOperationsInput | boolean + isRead?: BoolFieldUpdateOperationsInput | boolean + isStarred?: BoolFieldUpdateOperationsInput | boolean + isDeleted?: BoolFieldUpdateOperationsInput | boolean + deletedAt?: NullableDateTimeFieldUpdateOperationsInput | Date | string | null + createdAt?: DateTimeFieldUpdateOperationsInput | Date | string + updatedAt?: DateTimeFieldUpdateOperationsInput | Date | string + } + + export type CachedEmailUncheckedUpdateManyInput = { + id?: IntFieldUpdateOperationsInput | number + stressfreiEmailId?: IntFieldUpdateOperationsInput | number + folder?: EnumEmailFolderFieldUpdateOperationsInput | $Enums.EmailFolder + messageId?: StringFieldUpdateOperationsInput | string + uid?: IntFieldUpdateOperationsInput | number + subject?: NullableStringFieldUpdateOperationsInput | string | null + fromAddress?: StringFieldUpdateOperationsInput | string + fromName?: NullableStringFieldUpdateOperationsInput | string | null + toAddresses?: StringFieldUpdateOperationsInput | string + ccAddresses?: NullableStringFieldUpdateOperationsInput | string | null + receivedAt?: DateTimeFieldUpdateOperationsInput | Date | string + textBody?: NullableStringFieldUpdateOperationsInput | string | null + htmlBody?: NullableStringFieldUpdateOperationsInput | string | null + hasAttachments?: BoolFieldUpdateOperationsInput | boolean + attachmentNames?: NullableStringFieldUpdateOperationsInput | string | null + contractId?: NullableIntFieldUpdateOperationsInput | number | null + assignedAt?: NullableDateTimeFieldUpdateOperationsInput | Date | string | null + assignedBy?: NullableIntFieldUpdateOperationsInput | number | null + isAutoAssigned?: BoolFieldUpdateOperationsInput | boolean + isRead?: BoolFieldUpdateOperationsInput | boolean + isStarred?: BoolFieldUpdateOperationsInput | boolean + isDeleted?: BoolFieldUpdateOperationsInput | boolean + deletedAt?: NullableDateTimeFieldUpdateOperationsInput | Date | string | null createdAt?: DateTimeFieldUpdateOperationsInput | Date | string updatedAt?: DateTimeFieldUpdateOperationsInput | Date | string } @@ -40085,6 +42081,7 @@ export namespace Prisma { tvDetails?: TvContractDetailsCreateNestedOneWithoutContractInput carInsuranceDetails?: CarInsuranceDetailsCreateNestedOneWithoutContractInput tasks?: ContractTaskCreateNestedManyWithoutContractInput + assignedEmails?: CachedEmailCreateNestedManyWithoutContractInput } export type ContractUncheckedCreateInput = { @@ -40132,6 +42129,7 @@ export namespace Prisma { tvDetails?: TvContractDetailsUncheckedCreateNestedOneWithoutContractInput carInsuranceDetails?: CarInsuranceDetailsUncheckedCreateNestedOneWithoutContractInput tasks?: ContractTaskUncheckedCreateNestedManyWithoutContractInput + assignedEmails?: CachedEmailUncheckedCreateNestedManyWithoutContractInput } export type ContractUpdateInput = { @@ -40178,6 +42176,7 @@ export namespace Prisma { tvDetails?: TvContractDetailsUpdateOneWithoutContractNestedInput carInsuranceDetails?: CarInsuranceDetailsUpdateOneWithoutContractNestedInput tasks?: ContractTaskUpdateManyWithoutContractNestedInput + assignedEmails?: CachedEmailUpdateManyWithoutContractNestedInput } export type ContractUncheckedUpdateInput = { @@ -40225,6 +42224,7 @@ export namespace Prisma { tvDetails?: TvContractDetailsUncheckedUpdateOneWithoutContractNestedInput carInsuranceDetails?: CarInsuranceDetailsUncheckedUpdateOneWithoutContractNestedInput tasks?: ContractTaskUncheckedUpdateManyWithoutContractNestedInput + assignedEmails?: CachedEmailUncheckedUpdateManyWithoutContractNestedInput } export type ContractCreateManyInput = { @@ -41206,6 +43206,17 @@ export namespace Prisma { not?: NestedBoolFilter<$PrismaModel> | boolean } + export type DateTimeNullableFilter<$PrismaModel = never> = { + equals?: Date | string | DateTimeFieldRefInput<$PrismaModel> | null + in?: Date[] | string[] | null + notIn?: Date[] | string[] | null + lt?: Date | string | DateTimeFieldRefInput<$PrismaModel> + lte?: Date | string | DateTimeFieldRefInput<$PrismaModel> + gt?: Date | string | DateTimeFieldRefInput<$PrismaModel> + gte?: Date | string | DateTimeFieldRefInput<$PrismaModel> + not?: NestedDateTimeNullableFilter<$PrismaModel> | Date | string | null + } + export type IntNullableFilter<$PrismaModel = never> = { equals?: number | IntFieldRefInput<$PrismaModel> | null in?: number[] | null @@ -41244,6 +43255,7 @@ export namespace Prisma { firstName?: SortOrder lastName?: SortOrder isActive?: SortOrder + tokenInvalidatedAt?: SortOrder customerId?: SortOrder createdAt?: SortOrder updatedAt?: SortOrder @@ -41261,6 +43273,7 @@ export namespace Prisma { firstName?: SortOrder lastName?: SortOrder isActive?: SortOrder + tokenInvalidatedAt?: SortOrder customerId?: SortOrder createdAt?: SortOrder updatedAt?: SortOrder @@ -41273,6 +43286,7 @@ export namespace Prisma { firstName?: SortOrder lastName?: SortOrder isActive?: SortOrder + tokenInvalidatedAt?: SortOrder customerId?: SortOrder createdAt?: SortOrder updatedAt?: SortOrder @@ -41291,6 +43305,20 @@ export namespace Prisma { _max?: NestedBoolFilter<$PrismaModel> } + export type DateTimeNullableWithAggregatesFilter<$PrismaModel = never> = { + equals?: Date | string | DateTimeFieldRefInput<$PrismaModel> | null + in?: Date[] | string[] | null + notIn?: Date[] | string[] | null + lt?: Date | string | DateTimeFieldRefInput<$PrismaModel> + lte?: Date | string | DateTimeFieldRefInput<$PrismaModel> + gt?: Date | string | DateTimeFieldRefInput<$PrismaModel> + gte?: Date | string | DateTimeFieldRefInput<$PrismaModel> + not?: NestedDateTimeNullableWithAggregatesFilter<$PrismaModel> | Date | string | null + _count?: NestedIntNullableFilter<$PrismaModel> + _min?: NestedDateTimeNullableFilter<$PrismaModel> + _max?: NestedDateTimeNullableFilter<$PrismaModel> + } + export type IntNullableWithAggregatesFilter<$PrismaModel = never> = { equals?: number | IntFieldRefInput<$PrismaModel> | null in?: number[] | null @@ -41493,17 +43521,6 @@ export namespace Prisma { not?: NestedEnumCustomerTypeFilter<$PrismaModel> | $Enums.CustomerType } - export type DateTimeNullableFilter<$PrismaModel = never> = { - equals?: Date | string | DateTimeFieldRefInput<$PrismaModel> | null - in?: Date[] | string[] | null - notIn?: Date[] | string[] | null - lt?: Date | string | DateTimeFieldRefInput<$PrismaModel> - lte?: Date | string | DateTimeFieldRefInput<$PrismaModel> - gt?: Date | string | DateTimeFieldRefInput<$PrismaModel> - gte?: Date | string | DateTimeFieldRefInput<$PrismaModel> - not?: NestedDateTimeNullableFilter<$PrismaModel> | Date | string | null - } - export type UserNullableRelationFilter = { is?: UserWhereInput | null isNot?: UserWhereInput | null @@ -41684,20 +43701,6 @@ export namespace Prisma { _max?: NestedEnumCustomerTypeFilter<$PrismaModel> } - export type DateTimeNullableWithAggregatesFilter<$PrismaModel = never> = { - equals?: Date | string | DateTimeFieldRefInput<$PrismaModel> | null - in?: Date[] | string[] | null - notIn?: Date[] | string[] | null - lt?: Date | string | DateTimeFieldRefInput<$PrismaModel> - lte?: Date | string | DateTimeFieldRefInput<$PrismaModel> - gt?: Date | string | DateTimeFieldRefInput<$PrismaModel> - gte?: Date | string | DateTimeFieldRefInput<$PrismaModel> - not?: NestedDateTimeNullableWithAggregatesFilter<$PrismaModel> | Date | string | null - _count?: NestedIntNullableFilter<$PrismaModel> - _min?: NestedDateTimeNullableFilter<$PrismaModel> - _max?: NestedDateTimeNullableFilter<$PrismaModel> - } - export type CustomerRelationFilter = { is?: CustomerWhereInput isNot?: CustomerWhereInput @@ -41953,6 +43956,13 @@ export namespace Prisma { not?: NestedEnumEmailProviderTypeFilter<$PrismaModel> | $Enums.EmailProviderType } + export type EnumMailEncryptionFilter<$PrismaModel = never> = { + equals?: $Enums.MailEncryption | EnumMailEncryptionFieldRefInput<$PrismaModel> + in?: $Enums.MailEncryption[] + notIn?: $Enums.MailEncryption[] + not?: NestedEnumMailEncryptionFilter<$PrismaModel> | $Enums.MailEncryption + } + export type EmailProviderConfigCountOrderByAggregateInput = { id?: SortOrder name?: SortOrder @@ -41963,6 +43973,13 @@ export namespace Prisma { passwordEncrypted?: SortOrder domain?: SortOrder defaultForwardEmail?: SortOrder + imapServer?: SortOrder + imapPort?: SortOrder + smtpServer?: SortOrder + smtpPort?: SortOrder + imapEncryption?: SortOrder + smtpEncryption?: SortOrder + allowSelfSignedCerts?: SortOrder isActive?: SortOrder isDefault?: SortOrder createdAt?: SortOrder @@ -41971,6 +43988,8 @@ export namespace Prisma { export type EmailProviderConfigAvgOrderByAggregateInput = { id?: SortOrder + imapPort?: SortOrder + smtpPort?: SortOrder } export type EmailProviderConfigMaxOrderByAggregateInput = { @@ -41983,6 +44002,13 @@ export namespace Prisma { passwordEncrypted?: SortOrder domain?: SortOrder defaultForwardEmail?: SortOrder + imapServer?: SortOrder + imapPort?: SortOrder + smtpServer?: SortOrder + smtpPort?: SortOrder + imapEncryption?: SortOrder + smtpEncryption?: SortOrder + allowSelfSignedCerts?: SortOrder isActive?: SortOrder isDefault?: SortOrder createdAt?: SortOrder @@ -41999,6 +44025,13 @@ export namespace Prisma { passwordEncrypted?: SortOrder domain?: SortOrder defaultForwardEmail?: SortOrder + imapServer?: SortOrder + imapPort?: SortOrder + smtpServer?: SortOrder + smtpPort?: SortOrder + imapEncryption?: SortOrder + smtpEncryption?: SortOrder + allowSelfSignedCerts?: SortOrder isActive?: SortOrder isDefault?: SortOrder createdAt?: SortOrder @@ -42007,6 +44040,8 @@ export namespace Prisma { export type EmailProviderConfigSumOrderByAggregateInput = { id?: SortOrder + imapPort?: SortOrder + smtpPort?: SortOrder } export type EnumEmailProviderTypeWithAggregatesFilter<$PrismaModel = never> = { @@ -42019,6 +44054,26 @@ export namespace Prisma { _max?: NestedEnumEmailProviderTypeFilter<$PrismaModel> } + export type EnumMailEncryptionWithAggregatesFilter<$PrismaModel = never> = { + equals?: $Enums.MailEncryption | EnumMailEncryptionFieldRefInput<$PrismaModel> + in?: $Enums.MailEncryption[] + notIn?: $Enums.MailEncryption[] + not?: NestedEnumMailEncryptionWithAggregatesFilter<$PrismaModel> | $Enums.MailEncryption + _count?: NestedIntFilter<$PrismaModel> + _min?: NestedEnumMailEncryptionFilter<$PrismaModel> + _max?: NestedEnumMailEncryptionFilter<$PrismaModel> + } + + export type CachedEmailListRelationFilter = { + every?: CachedEmailWhereInput + some?: CachedEmailWhereInput + none?: CachedEmailWhereInput + } + + export type CachedEmailOrderByRelationAggregateInput = { + _count?: SortOrder + } + export type StressfreiEmailCountOrderByAggregateInput = { id?: SortOrder customerId?: SortOrder @@ -42029,6 +44084,8 @@ export namespace Prisma { isProvisioned?: SortOrder provisionedAt?: SortOrder provisionError?: SortOrder + hasMailbox?: SortOrder + emailPasswordEncrypted?: SortOrder createdAt?: SortOrder updatedAt?: SortOrder } @@ -42048,6 +44105,8 @@ export namespace Prisma { isProvisioned?: SortOrder provisionedAt?: SortOrder provisionError?: SortOrder + hasMailbox?: SortOrder + emailPasswordEncrypted?: SortOrder createdAt?: SortOrder updatedAt?: SortOrder } @@ -42062,6 +44121,8 @@ export namespace Prisma { isProvisioned?: SortOrder provisionedAt?: SortOrder provisionError?: SortOrder + hasMailbox?: SortOrder + emailPasswordEncrypted?: SortOrder createdAt?: SortOrder updatedAt?: SortOrder } @@ -42071,6 +44132,139 @@ export namespace Prisma { customerId?: SortOrder } + export type EnumEmailFolderFilter<$PrismaModel = never> = { + equals?: $Enums.EmailFolder | EnumEmailFolderFieldRefInput<$PrismaModel> + in?: $Enums.EmailFolder[] + notIn?: $Enums.EmailFolder[] + not?: NestedEnumEmailFolderFilter<$PrismaModel> | $Enums.EmailFolder + } + + export type StressfreiEmailRelationFilter = { + is?: StressfreiEmailWhereInput + isNot?: StressfreiEmailWhereInput + } + + export type ContractNullableRelationFilter = { + is?: ContractWhereInput | null + isNot?: ContractWhereInput | null + } + + export type CachedEmailStressfreiEmailIdMessageIdFolderCompoundUniqueInput = { + stressfreiEmailId: number + messageId: string + folder: $Enums.EmailFolder + } + + export type CachedEmailCountOrderByAggregateInput = { + id?: SortOrder + stressfreiEmailId?: SortOrder + folder?: SortOrder + messageId?: SortOrder + uid?: SortOrder + subject?: SortOrder + fromAddress?: SortOrder + fromName?: SortOrder + toAddresses?: SortOrder + ccAddresses?: SortOrder + receivedAt?: SortOrder + textBody?: SortOrder + htmlBody?: SortOrder + hasAttachments?: SortOrder + attachmentNames?: SortOrder + contractId?: SortOrder + assignedAt?: SortOrder + assignedBy?: SortOrder + isAutoAssigned?: SortOrder + isRead?: SortOrder + isStarred?: SortOrder + isDeleted?: SortOrder + deletedAt?: SortOrder + createdAt?: SortOrder + updatedAt?: SortOrder + } + + export type CachedEmailAvgOrderByAggregateInput = { + id?: SortOrder + stressfreiEmailId?: SortOrder + uid?: SortOrder + contractId?: SortOrder + assignedBy?: SortOrder + } + + export type CachedEmailMaxOrderByAggregateInput = { + id?: SortOrder + stressfreiEmailId?: SortOrder + folder?: SortOrder + messageId?: SortOrder + uid?: SortOrder + subject?: SortOrder + fromAddress?: SortOrder + fromName?: SortOrder + toAddresses?: SortOrder + ccAddresses?: SortOrder + receivedAt?: SortOrder + textBody?: SortOrder + htmlBody?: SortOrder + hasAttachments?: SortOrder + attachmentNames?: SortOrder + contractId?: SortOrder + assignedAt?: SortOrder + assignedBy?: SortOrder + isAutoAssigned?: SortOrder + isRead?: SortOrder + isStarred?: SortOrder + isDeleted?: SortOrder + deletedAt?: SortOrder + createdAt?: SortOrder + updatedAt?: SortOrder + } + + export type CachedEmailMinOrderByAggregateInput = { + id?: SortOrder + stressfreiEmailId?: SortOrder + folder?: SortOrder + messageId?: SortOrder + uid?: SortOrder + subject?: SortOrder + fromAddress?: SortOrder + fromName?: SortOrder + toAddresses?: SortOrder + ccAddresses?: SortOrder + receivedAt?: SortOrder + textBody?: SortOrder + htmlBody?: SortOrder + hasAttachments?: SortOrder + attachmentNames?: SortOrder + contractId?: SortOrder + assignedAt?: SortOrder + assignedBy?: SortOrder + isAutoAssigned?: SortOrder + isRead?: SortOrder + isStarred?: SortOrder + isDeleted?: SortOrder + deletedAt?: SortOrder + createdAt?: SortOrder + updatedAt?: SortOrder + } + + export type CachedEmailSumOrderByAggregateInput = { + id?: SortOrder + stressfreiEmailId?: SortOrder + uid?: SortOrder + contractId?: SortOrder + assignedBy?: SortOrder + } + + export type EnumEmailFolderWithAggregatesFilter<$PrismaModel = never> = { + equals?: $Enums.EmailFolder | EnumEmailFolderFieldRefInput<$PrismaModel> + in?: $Enums.EmailFolder[] + notIn?: $Enums.EmailFolder[] + not?: NestedEnumEmailFolderWithAggregatesFilter<$PrismaModel> | $Enums.EmailFolder + _count?: NestedIntFilter<$PrismaModel> + _min?: NestedEnumEmailFolderFilter<$PrismaModel> + _max?: NestedEnumEmailFolderFilter<$PrismaModel> + } + export type EnumMeterTypeFilter<$PrismaModel = never> = { equals?: $Enums.MeterType | EnumMeterTypeFieldRefInput<$PrismaModel> in?: $Enums.MeterType[] @@ -42534,11 +44728,6 @@ export namespace Prisma { isNot?: ContractDurationWhereInput | null } - export type ContractNullableRelationFilter = { - is?: ContractWhereInput | null - isNot?: ContractWhereInput | null - } - export type ProviderNullableRelationFilter = { is?: ProviderWhereInput | null isNot?: ProviderWhereInput | null @@ -43355,6 +45544,10 @@ export namespace Prisma { set?: boolean } + export type NullableDateTimeFieldUpdateOperationsInput = { + set?: Date | string | null + } + export type CustomerUpdateOneWithoutUserNestedInput = { create?: XOR connectOrCreate?: CustomerCreateOrConnectWithoutUserInput @@ -43715,10 +45908,6 @@ export namespace Prisma { set?: $Enums.CustomerType } - export type NullableDateTimeFieldUpdateOperationsInput = { - set?: Date | string | null - } - export type UserUpdateOneWithoutCustomerNestedInput = { create?: XOR connectOrCreate?: UserCreateOrConnectWithoutCustomerInput @@ -44171,6 +46360,10 @@ export namespace Prisma { set?: $Enums.EmailProviderType } + export type EnumMailEncryptionFieldUpdateOperationsInput = { + set?: $Enums.MailEncryption + } + export type CustomerCreateNestedOneWithoutStressfreiEmailsInput = { create?: XOR connectOrCreate?: CustomerCreateOrConnectWithoutStressfreiEmailsInput @@ -44184,6 +46377,13 @@ export namespace Prisma { connect?: ContractWhereUniqueInput | ContractWhereUniqueInput[] } + export type CachedEmailCreateNestedManyWithoutStressfreiEmailInput = { + create?: XOR | CachedEmailCreateWithoutStressfreiEmailInput[] | CachedEmailUncheckedCreateWithoutStressfreiEmailInput[] + connectOrCreate?: CachedEmailCreateOrConnectWithoutStressfreiEmailInput | CachedEmailCreateOrConnectWithoutStressfreiEmailInput[] + createMany?: CachedEmailCreateManyStressfreiEmailInputEnvelope + connect?: CachedEmailWhereUniqueInput | CachedEmailWhereUniqueInput[] + } + export type ContractUncheckedCreateNestedManyWithoutStressfreiEmailInput = { create?: XOR | ContractCreateWithoutStressfreiEmailInput[] | ContractUncheckedCreateWithoutStressfreiEmailInput[] connectOrCreate?: ContractCreateOrConnectWithoutStressfreiEmailInput | ContractCreateOrConnectWithoutStressfreiEmailInput[] @@ -44191,6 +46391,13 @@ export namespace Prisma { connect?: ContractWhereUniqueInput | ContractWhereUniqueInput[] } + export type CachedEmailUncheckedCreateNestedManyWithoutStressfreiEmailInput = { + create?: XOR | CachedEmailCreateWithoutStressfreiEmailInput[] | CachedEmailUncheckedCreateWithoutStressfreiEmailInput[] + connectOrCreate?: CachedEmailCreateOrConnectWithoutStressfreiEmailInput | CachedEmailCreateOrConnectWithoutStressfreiEmailInput[] + createMany?: CachedEmailCreateManyStressfreiEmailInputEnvelope + connect?: CachedEmailWhereUniqueInput | CachedEmailWhereUniqueInput[] + } + export type CustomerUpdateOneRequiredWithoutStressfreiEmailsNestedInput = { create?: XOR connectOrCreate?: CustomerCreateOrConnectWithoutStressfreiEmailsInput @@ -44213,6 +46420,20 @@ export namespace Prisma { deleteMany?: ContractScalarWhereInput | ContractScalarWhereInput[] } + export type CachedEmailUpdateManyWithoutStressfreiEmailNestedInput = { + create?: XOR | CachedEmailCreateWithoutStressfreiEmailInput[] | CachedEmailUncheckedCreateWithoutStressfreiEmailInput[] + connectOrCreate?: CachedEmailCreateOrConnectWithoutStressfreiEmailInput | CachedEmailCreateOrConnectWithoutStressfreiEmailInput[] + upsert?: CachedEmailUpsertWithWhereUniqueWithoutStressfreiEmailInput | CachedEmailUpsertWithWhereUniqueWithoutStressfreiEmailInput[] + createMany?: CachedEmailCreateManyStressfreiEmailInputEnvelope + set?: CachedEmailWhereUniqueInput | CachedEmailWhereUniqueInput[] + disconnect?: CachedEmailWhereUniqueInput | CachedEmailWhereUniqueInput[] + delete?: CachedEmailWhereUniqueInput | CachedEmailWhereUniqueInput[] + connect?: CachedEmailWhereUniqueInput | CachedEmailWhereUniqueInput[] + update?: CachedEmailUpdateWithWhereUniqueWithoutStressfreiEmailInput | CachedEmailUpdateWithWhereUniqueWithoutStressfreiEmailInput[] + updateMany?: CachedEmailUpdateManyWithWhereWithoutStressfreiEmailInput | CachedEmailUpdateManyWithWhereWithoutStressfreiEmailInput[] + deleteMany?: CachedEmailScalarWhereInput | CachedEmailScalarWhereInput[] + } + export type ContractUncheckedUpdateManyWithoutStressfreiEmailNestedInput = { create?: XOR | ContractCreateWithoutStressfreiEmailInput[] | ContractUncheckedCreateWithoutStressfreiEmailInput[] connectOrCreate?: ContractCreateOrConnectWithoutStressfreiEmailInput | ContractCreateOrConnectWithoutStressfreiEmailInput[] @@ -44227,6 +46448,54 @@ export namespace Prisma { deleteMany?: ContractScalarWhereInput | ContractScalarWhereInput[] } + export type CachedEmailUncheckedUpdateManyWithoutStressfreiEmailNestedInput = { + create?: XOR | CachedEmailCreateWithoutStressfreiEmailInput[] | CachedEmailUncheckedCreateWithoutStressfreiEmailInput[] + connectOrCreate?: CachedEmailCreateOrConnectWithoutStressfreiEmailInput | CachedEmailCreateOrConnectWithoutStressfreiEmailInput[] + upsert?: CachedEmailUpsertWithWhereUniqueWithoutStressfreiEmailInput | CachedEmailUpsertWithWhereUniqueWithoutStressfreiEmailInput[] + createMany?: CachedEmailCreateManyStressfreiEmailInputEnvelope + set?: CachedEmailWhereUniqueInput | CachedEmailWhereUniqueInput[] + disconnect?: CachedEmailWhereUniqueInput | CachedEmailWhereUniqueInput[] + delete?: CachedEmailWhereUniqueInput | CachedEmailWhereUniqueInput[] + connect?: CachedEmailWhereUniqueInput | CachedEmailWhereUniqueInput[] + update?: CachedEmailUpdateWithWhereUniqueWithoutStressfreiEmailInput | CachedEmailUpdateWithWhereUniqueWithoutStressfreiEmailInput[] + updateMany?: CachedEmailUpdateManyWithWhereWithoutStressfreiEmailInput | CachedEmailUpdateManyWithWhereWithoutStressfreiEmailInput[] + deleteMany?: CachedEmailScalarWhereInput | CachedEmailScalarWhereInput[] + } + + export type StressfreiEmailCreateNestedOneWithoutCachedEmailsInput = { + create?: XOR + connectOrCreate?: StressfreiEmailCreateOrConnectWithoutCachedEmailsInput + connect?: StressfreiEmailWhereUniqueInput + } + + export type ContractCreateNestedOneWithoutAssignedEmailsInput = { + create?: XOR + connectOrCreate?: ContractCreateOrConnectWithoutAssignedEmailsInput + connect?: ContractWhereUniqueInput + } + + export type EnumEmailFolderFieldUpdateOperationsInput = { + set?: $Enums.EmailFolder + } + + export type StressfreiEmailUpdateOneRequiredWithoutCachedEmailsNestedInput = { + create?: XOR + connectOrCreate?: StressfreiEmailCreateOrConnectWithoutCachedEmailsInput + upsert?: StressfreiEmailUpsertWithoutCachedEmailsInput + connect?: StressfreiEmailWhereUniqueInput + update?: XOR, StressfreiEmailUncheckedUpdateWithoutCachedEmailsInput> + } + + export type ContractUpdateOneWithoutAssignedEmailsNestedInput = { + create?: XOR + connectOrCreate?: ContractCreateOrConnectWithoutAssignedEmailsInput + upsert?: ContractUpsertWithoutAssignedEmailsInput + disconnect?: ContractWhereInput | boolean + delete?: ContractWhereInput | boolean + connect?: ContractWhereUniqueInput + update?: XOR, ContractUncheckedUpdateWithoutAssignedEmailsInput> + } + export type CustomerCreateNestedOneWithoutMetersInput = { create?: XOR connectOrCreate?: CustomerCreateOrConnectWithoutMetersInput @@ -44774,6 +47043,13 @@ export namespace Prisma { connect?: ContractTaskWhereUniqueInput | ContractTaskWhereUniqueInput[] } + export type CachedEmailCreateNestedManyWithoutContractInput = { + create?: XOR | CachedEmailCreateWithoutContractInput[] | CachedEmailUncheckedCreateWithoutContractInput[] + connectOrCreate?: CachedEmailCreateOrConnectWithoutContractInput | CachedEmailCreateOrConnectWithoutContractInput[] + createMany?: CachedEmailCreateManyContractInputEnvelope + connect?: CachedEmailWhereUniqueInput | CachedEmailWhereUniqueInput[] + } + export type ContractUncheckedCreateNestedOneWithoutPreviousContractInput = { create?: XOR connectOrCreate?: ContractCreateOrConnectWithoutPreviousContractInput @@ -44817,6 +47093,13 @@ export namespace Prisma { connect?: ContractTaskWhereUniqueInput | ContractTaskWhereUniqueInput[] } + export type CachedEmailUncheckedCreateNestedManyWithoutContractInput = { + create?: XOR | CachedEmailCreateWithoutContractInput[] | CachedEmailUncheckedCreateWithoutContractInput[] + connectOrCreate?: CachedEmailCreateOrConnectWithoutContractInput | CachedEmailCreateOrConnectWithoutContractInput[] + createMany?: CachedEmailCreateManyContractInputEnvelope + connect?: CachedEmailWhereUniqueInput | CachedEmailWhereUniqueInput[] + } + export type EnumContractTypeFieldUpdateOperationsInput = { set?: $Enums.ContractType } @@ -45025,6 +47308,20 @@ export namespace Prisma { deleteMany?: ContractTaskScalarWhereInput | ContractTaskScalarWhereInput[] } + export type CachedEmailUpdateManyWithoutContractNestedInput = { + create?: XOR | CachedEmailCreateWithoutContractInput[] | CachedEmailUncheckedCreateWithoutContractInput[] + connectOrCreate?: CachedEmailCreateOrConnectWithoutContractInput | CachedEmailCreateOrConnectWithoutContractInput[] + upsert?: CachedEmailUpsertWithWhereUniqueWithoutContractInput | CachedEmailUpsertWithWhereUniqueWithoutContractInput[] + createMany?: CachedEmailCreateManyContractInputEnvelope + set?: CachedEmailWhereUniqueInput | CachedEmailWhereUniqueInput[] + disconnect?: CachedEmailWhereUniqueInput | CachedEmailWhereUniqueInput[] + delete?: CachedEmailWhereUniqueInput | CachedEmailWhereUniqueInput[] + connect?: CachedEmailWhereUniqueInput | CachedEmailWhereUniqueInput[] + update?: CachedEmailUpdateWithWhereUniqueWithoutContractInput | CachedEmailUpdateWithWhereUniqueWithoutContractInput[] + updateMany?: CachedEmailUpdateManyWithWhereWithoutContractInput | CachedEmailUpdateManyWithWhereWithoutContractInput[] + deleteMany?: CachedEmailScalarWhereInput | CachedEmailScalarWhereInput[] + } + export type ContractUncheckedUpdateOneWithoutPreviousContractNestedInput = { create?: XOR connectOrCreate?: ContractCreateOrConnectWithoutPreviousContractInput @@ -45099,6 +47396,20 @@ export namespace Prisma { deleteMany?: ContractTaskScalarWhereInput | ContractTaskScalarWhereInput[] } + export type CachedEmailUncheckedUpdateManyWithoutContractNestedInput = { + create?: XOR | CachedEmailCreateWithoutContractInput[] | CachedEmailUncheckedCreateWithoutContractInput[] + connectOrCreate?: CachedEmailCreateOrConnectWithoutContractInput | CachedEmailCreateOrConnectWithoutContractInput[] + upsert?: CachedEmailUpsertWithWhereUniqueWithoutContractInput | CachedEmailUpsertWithWhereUniqueWithoutContractInput[] + createMany?: CachedEmailCreateManyContractInputEnvelope + set?: CachedEmailWhereUniqueInput | CachedEmailWhereUniqueInput[] + disconnect?: CachedEmailWhereUniqueInput | CachedEmailWhereUniqueInput[] + delete?: CachedEmailWhereUniqueInput | CachedEmailWhereUniqueInput[] + connect?: CachedEmailWhereUniqueInput | CachedEmailWhereUniqueInput[] + update?: CachedEmailUpdateWithWhereUniqueWithoutContractInput | CachedEmailUpdateWithWhereUniqueWithoutContractInput[] + updateMany?: CachedEmailUpdateManyWithWhereWithoutContractInput | CachedEmailUpdateManyWithWhereWithoutContractInput[] + deleteMany?: CachedEmailScalarWhereInput | CachedEmailScalarWhereInput[] + } + export type ContractCreateNestedOneWithoutTasksInput = { create?: XOR connectOrCreate?: ContractCreateOrConnectWithoutTasksInput @@ -45474,6 +47785,17 @@ export namespace Prisma { not?: NestedBoolFilter<$PrismaModel> | boolean } + export type NestedDateTimeNullableFilter<$PrismaModel = never> = { + equals?: Date | string | DateTimeFieldRefInput<$PrismaModel> | null + in?: Date[] | string[] | null + notIn?: Date[] | string[] | null + lt?: Date | string | DateTimeFieldRefInput<$PrismaModel> + lte?: Date | string | DateTimeFieldRefInput<$PrismaModel> + gt?: Date | string | DateTimeFieldRefInput<$PrismaModel> + gte?: Date | string | DateTimeFieldRefInput<$PrismaModel> + not?: NestedDateTimeNullableFilter<$PrismaModel> | Date | string | null + } + export type NestedIntNullableFilter<$PrismaModel = never> = { equals?: number | IntFieldRefInput<$PrismaModel> | null in?: number[] | null @@ -45493,6 +47815,20 @@ export namespace Prisma { _max?: NestedBoolFilter<$PrismaModel> } + export type NestedDateTimeNullableWithAggregatesFilter<$PrismaModel = never> = { + equals?: Date | string | DateTimeFieldRefInput<$PrismaModel> | null + in?: Date[] | string[] | null + notIn?: Date[] | string[] | null + lt?: Date | string | DateTimeFieldRefInput<$PrismaModel> + lte?: Date | string | DateTimeFieldRefInput<$PrismaModel> + gt?: Date | string | DateTimeFieldRefInput<$PrismaModel> + gte?: Date | string | DateTimeFieldRefInput<$PrismaModel> + not?: NestedDateTimeNullableWithAggregatesFilter<$PrismaModel> | Date | string | null + _count?: NestedIntNullableFilter<$PrismaModel> + _min?: NestedDateTimeNullableFilter<$PrismaModel> + _max?: NestedDateTimeNullableFilter<$PrismaModel> + } + export type NestedIntNullableWithAggregatesFilter<$PrismaModel = never> = { equals?: number | IntFieldRefInput<$PrismaModel> | null in?: number[] | null @@ -45558,17 +47894,6 @@ export namespace Prisma { not?: NestedEnumCustomerTypeFilter<$PrismaModel> | $Enums.CustomerType } - export type NestedDateTimeNullableFilter<$PrismaModel = never> = { - equals?: Date | string | DateTimeFieldRefInput<$PrismaModel> | null - in?: Date[] | string[] | null - notIn?: Date[] | string[] | null - lt?: Date | string | DateTimeFieldRefInput<$PrismaModel> - lte?: Date | string | DateTimeFieldRefInput<$PrismaModel> - gt?: Date | string | DateTimeFieldRefInput<$PrismaModel> - gte?: Date | string | DateTimeFieldRefInput<$PrismaModel> - not?: NestedDateTimeNullableFilter<$PrismaModel> | Date | string | null - } - export type NestedEnumCustomerTypeWithAggregatesFilter<$PrismaModel = never> = { equals?: $Enums.CustomerType | EnumCustomerTypeFieldRefInput<$PrismaModel> in?: $Enums.CustomerType[] @@ -45579,20 +47904,6 @@ export namespace Prisma { _max?: NestedEnumCustomerTypeFilter<$PrismaModel> } - export type NestedDateTimeNullableWithAggregatesFilter<$PrismaModel = never> = { - equals?: Date | string | DateTimeFieldRefInput<$PrismaModel> | null - in?: Date[] | string[] | null - notIn?: Date[] | string[] | null - lt?: Date | string | DateTimeFieldRefInput<$PrismaModel> - lte?: Date | string | DateTimeFieldRefInput<$PrismaModel> - gt?: Date | string | DateTimeFieldRefInput<$PrismaModel> - gte?: Date | string | DateTimeFieldRefInput<$PrismaModel> - not?: NestedDateTimeNullableWithAggregatesFilter<$PrismaModel> | Date | string | null - _count?: NestedIntNullableFilter<$PrismaModel> - _min?: NestedDateTimeNullableFilter<$PrismaModel> - _max?: NestedDateTimeNullableFilter<$PrismaModel> - } - export type NestedEnumAddressTypeFilter<$PrismaModel = never> = { equals?: $Enums.AddressType | EnumAddressTypeFieldRefInput<$PrismaModel> in?: $Enums.AddressType[] @@ -45634,6 +47945,13 @@ export namespace Prisma { not?: NestedEnumEmailProviderTypeFilter<$PrismaModel> | $Enums.EmailProviderType } + export type NestedEnumMailEncryptionFilter<$PrismaModel = never> = { + equals?: $Enums.MailEncryption | EnumMailEncryptionFieldRefInput<$PrismaModel> + in?: $Enums.MailEncryption[] + notIn?: $Enums.MailEncryption[] + not?: NestedEnumMailEncryptionFilter<$PrismaModel> | $Enums.MailEncryption + } + export type NestedEnumEmailProviderTypeWithAggregatesFilter<$PrismaModel = never> = { equals?: $Enums.EmailProviderType | EnumEmailProviderTypeFieldRefInput<$PrismaModel> in?: $Enums.EmailProviderType[] @@ -45644,6 +47962,33 @@ export namespace Prisma { _max?: NestedEnumEmailProviderTypeFilter<$PrismaModel> } + export type NestedEnumMailEncryptionWithAggregatesFilter<$PrismaModel = never> = { + equals?: $Enums.MailEncryption | EnumMailEncryptionFieldRefInput<$PrismaModel> + in?: $Enums.MailEncryption[] + notIn?: $Enums.MailEncryption[] + not?: NestedEnumMailEncryptionWithAggregatesFilter<$PrismaModel> | $Enums.MailEncryption + _count?: NestedIntFilter<$PrismaModel> + _min?: NestedEnumMailEncryptionFilter<$PrismaModel> + _max?: NestedEnumMailEncryptionFilter<$PrismaModel> + } + + export type NestedEnumEmailFolderFilter<$PrismaModel = never> = { + equals?: $Enums.EmailFolder | EnumEmailFolderFieldRefInput<$PrismaModel> + in?: $Enums.EmailFolder[] + notIn?: $Enums.EmailFolder[] + not?: NestedEnumEmailFolderFilter<$PrismaModel> | $Enums.EmailFolder + } + + export type NestedEnumEmailFolderWithAggregatesFilter<$PrismaModel = never> = { + equals?: $Enums.EmailFolder | EnumEmailFolderFieldRefInput<$PrismaModel> + in?: $Enums.EmailFolder[] + notIn?: $Enums.EmailFolder[] + not?: NestedEnumEmailFolderWithAggregatesFilter<$PrismaModel> | $Enums.EmailFolder + _count?: NestedIntFilter<$PrismaModel> + _min?: NestedEnumEmailFolderFilter<$PrismaModel> + _max?: NestedEnumEmailFolderFilter<$PrismaModel> + } + export type NestedEnumMeterTypeFilter<$PrismaModel = never> = { equals?: $Enums.MeterType | EnumMeterTypeFieldRefInput<$PrismaModel> in?: $Enums.MeterType[] @@ -46169,6 +48514,7 @@ export namespace Prisma { firstName: string lastName: string isActive?: boolean + tokenInvalidatedAt?: Date | string | null createdAt?: Date | string updatedAt?: Date | string customer?: CustomerCreateNestedOneWithoutUserInput @@ -46181,6 +48527,7 @@ export namespace Prisma { firstName: string lastName: string isActive?: boolean + tokenInvalidatedAt?: Date | string | null customerId?: number | null createdAt?: Date | string updatedAt?: Date | string @@ -46230,6 +48577,7 @@ export namespace Prisma { firstName?: StringFieldUpdateOperationsInput | string lastName?: StringFieldUpdateOperationsInput | string isActive?: BoolFieldUpdateOperationsInput | boolean + tokenInvalidatedAt?: NullableDateTimeFieldUpdateOperationsInput | Date | string | null createdAt?: DateTimeFieldUpdateOperationsInput | Date | string updatedAt?: DateTimeFieldUpdateOperationsInput | Date | string customer?: CustomerUpdateOneWithoutUserNestedInput @@ -46242,6 +48590,7 @@ export namespace Prisma { firstName?: StringFieldUpdateOperationsInput | string lastName?: StringFieldUpdateOperationsInput | string isActive?: BoolFieldUpdateOperationsInput | boolean + tokenInvalidatedAt?: NullableDateTimeFieldUpdateOperationsInput | Date | string | null customerId?: NullableIntFieldUpdateOperationsInput | number | null createdAt?: DateTimeFieldUpdateOperationsInput | Date | string updatedAt?: DateTimeFieldUpdateOperationsInput | Date | string @@ -46281,6 +48630,7 @@ export namespace Prisma { firstName: string lastName: string isActive?: boolean + tokenInvalidatedAt?: Date | string | null createdAt?: Date | string updatedAt?: Date | string roles?: UserRoleCreateNestedManyWithoutUserInput @@ -46293,6 +48643,7 @@ export namespace Prisma { firstName: string lastName: string isActive?: boolean + tokenInvalidatedAt?: Date | string | null createdAt?: Date | string updatedAt?: Date | string roles?: UserRoleUncheckedCreateNestedManyWithoutUserInput @@ -46459,9 +48810,12 @@ export namespace Prisma { isProvisioned?: boolean provisionedAt?: Date | string | null provisionError?: string | null + hasMailbox?: boolean + emailPasswordEncrypted?: string | null createdAt?: Date | string updatedAt?: Date | string contracts?: ContractCreateNestedManyWithoutStressfreiEmailInput + cachedEmails?: CachedEmailCreateNestedManyWithoutStressfreiEmailInput } export type StressfreiEmailUncheckedCreateWithoutCustomerInput = { @@ -46473,9 +48827,12 @@ export namespace Prisma { isProvisioned?: boolean provisionedAt?: Date | string | null provisionError?: string | null + hasMailbox?: boolean + emailPasswordEncrypted?: string | null createdAt?: Date | string updatedAt?: Date | string contracts?: ContractUncheckedCreateNestedManyWithoutStressfreiEmailInput + cachedEmails?: CachedEmailUncheckedCreateNestedManyWithoutStressfreiEmailInput } export type StressfreiEmailCreateOrConnectWithoutCustomerInput = { @@ -46531,6 +48888,7 @@ export namespace Prisma { tvDetails?: TvContractDetailsCreateNestedOneWithoutContractInput carInsuranceDetails?: CarInsuranceDetailsCreateNestedOneWithoutContractInput tasks?: ContractTaskCreateNestedManyWithoutContractInput + assignedEmails?: CachedEmailCreateNestedManyWithoutContractInput } export type ContractUncheckedCreateWithoutCustomerInput = { @@ -46577,6 +48935,7 @@ export namespace Prisma { tvDetails?: TvContractDetailsUncheckedCreateNestedOneWithoutContractInput carInsuranceDetails?: CarInsuranceDetailsUncheckedCreateNestedOneWithoutContractInput tasks?: ContractTaskUncheckedCreateNestedManyWithoutContractInput + assignedEmails?: CachedEmailUncheckedCreateNestedManyWithoutContractInput } export type ContractCreateOrConnectWithoutCustomerInput = { @@ -46660,6 +49019,7 @@ export namespace Prisma { firstName?: StringFieldUpdateOperationsInput | string lastName?: StringFieldUpdateOperationsInput | string isActive?: BoolFieldUpdateOperationsInput | boolean + tokenInvalidatedAt?: NullableDateTimeFieldUpdateOperationsInput | Date | string | null createdAt?: DateTimeFieldUpdateOperationsInput | Date | string updatedAt?: DateTimeFieldUpdateOperationsInput | Date | string roles?: UserRoleUpdateManyWithoutUserNestedInput @@ -46672,6 +49032,7 @@ export namespace Prisma { firstName?: StringFieldUpdateOperationsInput | string lastName?: StringFieldUpdateOperationsInput | string isActive?: BoolFieldUpdateOperationsInput | boolean + tokenInvalidatedAt?: NullableDateTimeFieldUpdateOperationsInput | Date | string | null createdAt?: DateTimeFieldUpdateOperationsInput | Date | string updatedAt?: DateTimeFieldUpdateOperationsInput | Date | string roles?: UserRoleUncheckedUpdateManyWithoutUserNestedInput @@ -46837,6 +49198,8 @@ export namespace Prisma { isProvisioned?: BoolFilter<"StressfreiEmail"> | boolean provisionedAt?: DateTimeNullableFilter<"StressfreiEmail"> | Date | string | null provisionError?: StringNullableFilter<"StressfreiEmail"> | string | null + hasMailbox?: BoolFilter<"StressfreiEmail"> | boolean + emailPasswordEncrypted?: StringNullableFilter<"StressfreiEmail"> | string | null createdAt?: DateTimeFilter<"StressfreiEmail"> | Date | string updatedAt?: DateTimeFilter<"StressfreiEmail"> | Date | string } @@ -47390,6 +49753,7 @@ export namespace Prisma { tvDetails?: TvContractDetailsCreateNestedOneWithoutContractInput carInsuranceDetails?: CarInsuranceDetailsCreateNestedOneWithoutContractInput tasks?: ContractTaskCreateNestedManyWithoutContractInput + assignedEmails?: CachedEmailCreateNestedManyWithoutContractInput } export type ContractUncheckedCreateWithoutAddressInput = { @@ -47436,6 +49800,7 @@ export namespace Prisma { tvDetails?: TvContractDetailsUncheckedCreateNestedOneWithoutContractInput carInsuranceDetails?: CarInsuranceDetailsUncheckedCreateNestedOneWithoutContractInput tasks?: ContractTaskUncheckedCreateNestedManyWithoutContractInput + assignedEmails?: CachedEmailUncheckedCreateNestedManyWithoutContractInput } export type ContractCreateOrConnectWithoutAddressInput = { @@ -47669,6 +50034,7 @@ export namespace Prisma { tvDetails?: TvContractDetailsCreateNestedOneWithoutContractInput carInsuranceDetails?: CarInsuranceDetailsCreateNestedOneWithoutContractInput tasks?: ContractTaskCreateNestedManyWithoutContractInput + assignedEmails?: CachedEmailCreateNestedManyWithoutContractInput } export type ContractUncheckedCreateWithoutBankCardInput = { @@ -47715,6 +50081,7 @@ export namespace Prisma { tvDetails?: TvContractDetailsUncheckedCreateNestedOneWithoutContractInput carInsuranceDetails?: CarInsuranceDetailsUncheckedCreateNestedOneWithoutContractInput tasks?: ContractTaskUncheckedCreateNestedManyWithoutContractInput + assignedEmails?: CachedEmailUncheckedCreateNestedManyWithoutContractInput } export type ContractCreateOrConnectWithoutBankCardInput = { @@ -47948,6 +50315,7 @@ export namespace Prisma { tvDetails?: TvContractDetailsCreateNestedOneWithoutContractInput carInsuranceDetails?: CarInsuranceDetailsCreateNestedOneWithoutContractInput tasks?: ContractTaskCreateNestedManyWithoutContractInput + assignedEmails?: CachedEmailCreateNestedManyWithoutContractInput } export type ContractUncheckedCreateWithoutIdentityDocumentInput = { @@ -47994,6 +50362,7 @@ export namespace Prisma { tvDetails?: TvContractDetailsUncheckedCreateNestedOneWithoutContractInput carInsuranceDetails?: CarInsuranceDetailsUncheckedCreateNestedOneWithoutContractInput tasks?: ContractTaskUncheckedCreateNestedManyWithoutContractInput + assignedEmails?: CachedEmailUncheckedCreateNestedManyWithoutContractInput } export type ContractCreateOrConnectWithoutIdentityDocumentInput = { @@ -48227,6 +50596,7 @@ export namespace Prisma { tvDetails?: TvContractDetailsCreateNestedOneWithoutContractInput carInsuranceDetails?: CarInsuranceDetailsCreateNestedOneWithoutContractInput tasks?: ContractTaskCreateNestedManyWithoutContractInput + assignedEmails?: CachedEmailCreateNestedManyWithoutContractInput } export type ContractUncheckedCreateWithoutStressfreiEmailInput = { @@ -48273,6 +50643,7 @@ export namespace Prisma { tvDetails?: TvContractDetailsUncheckedCreateNestedOneWithoutContractInput carInsuranceDetails?: CarInsuranceDetailsUncheckedCreateNestedOneWithoutContractInput tasks?: ContractTaskUncheckedCreateNestedManyWithoutContractInput + assignedEmails?: CachedEmailUncheckedCreateNestedManyWithoutContractInput } export type ContractCreateOrConnectWithoutStressfreiEmailInput = { @@ -48285,6 +50656,69 @@ export namespace Prisma { skipDuplicates?: boolean } + export type CachedEmailCreateWithoutStressfreiEmailInput = { + folder?: $Enums.EmailFolder + messageId: string + uid: number + subject?: string | null + fromAddress: string + fromName?: string | null + toAddresses: string + ccAddresses?: string | null + receivedAt: Date | string + textBody?: string | null + htmlBody?: string | null + hasAttachments?: boolean + attachmentNames?: string | null + assignedAt?: Date | string | null + assignedBy?: number | null + isAutoAssigned?: boolean + isRead?: boolean + isStarred?: boolean + isDeleted?: boolean + deletedAt?: Date | string | null + createdAt?: Date | string + updatedAt?: Date | string + contract?: ContractCreateNestedOneWithoutAssignedEmailsInput + } + + export type CachedEmailUncheckedCreateWithoutStressfreiEmailInput = { + id?: number + folder?: $Enums.EmailFolder + messageId: string + uid: number + subject?: string | null + fromAddress: string + fromName?: string | null + toAddresses: string + ccAddresses?: string | null + receivedAt: Date | string + textBody?: string | null + htmlBody?: string | null + hasAttachments?: boolean + attachmentNames?: string | null + contractId?: number | null + assignedAt?: Date | string | null + assignedBy?: number | null + isAutoAssigned?: boolean + isRead?: boolean + isStarred?: boolean + isDeleted?: boolean + deletedAt?: Date | string | null + createdAt?: Date | string + updatedAt?: Date | string + } + + export type CachedEmailCreateOrConnectWithoutStressfreiEmailInput = { + where: CachedEmailWhereUniqueInput + create: XOR + } + + export type CachedEmailCreateManyStressfreiEmailInputEnvelope = { + data: CachedEmailCreateManyStressfreiEmailInput | CachedEmailCreateManyStressfreiEmailInput[] + skipDuplicates?: boolean + } + export type CustomerUpsertWithoutStressfreiEmailsInput = { update: XOR create: XOR @@ -48385,6 +50819,337 @@ export namespace Prisma { data: XOR } + export type CachedEmailUpsertWithWhereUniqueWithoutStressfreiEmailInput = { + where: CachedEmailWhereUniqueInput + update: XOR + create: XOR + } + + export type CachedEmailUpdateWithWhereUniqueWithoutStressfreiEmailInput = { + where: CachedEmailWhereUniqueInput + data: XOR + } + + export type CachedEmailUpdateManyWithWhereWithoutStressfreiEmailInput = { + where: CachedEmailScalarWhereInput + data: XOR + } + + export type CachedEmailScalarWhereInput = { + AND?: CachedEmailScalarWhereInput | CachedEmailScalarWhereInput[] + OR?: CachedEmailScalarWhereInput[] + NOT?: CachedEmailScalarWhereInput | CachedEmailScalarWhereInput[] + id?: IntFilter<"CachedEmail"> | number + stressfreiEmailId?: IntFilter<"CachedEmail"> | number + folder?: EnumEmailFolderFilter<"CachedEmail"> | $Enums.EmailFolder + messageId?: StringFilter<"CachedEmail"> | string + uid?: IntFilter<"CachedEmail"> | number + subject?: StringNullableFilter<"CachedEmail"> | string | null + fromAddress?: StringFilter<"CachedEmail"> | string + fromName?: StringNullableFilter<"CachedEmail"> | string | null + toAddresses?: StringFilter<"CachedEmail"> | string + ccAddresses?: StringNullableFilter<"CachedEmail"> | string | null + receivedAt?: DateTimeFilter<"CachedEmail"> | Date | string + textBody?: StringNullableFilter<"CachedEmail"> | string | null + htmlBody?: StringNullableFilter<"CachedEmail"> | string | null + hasAttachments?: BoolFilter<"CachedEmail"> | boolean + attachmentNames?: StringNullableFilter<"CachedEmail"> | string | null + contractId?: IntNullableFilter<"CachedEmail"> | number | null + assignedAt?: DateTimeNullableFilter<"CachedEmail"> | Date | string | null + assignedBy?: IntNullableFilter<"CachedEmail"> | number | null + isAutoAssigned?: BoolFilter<"CachedEmail"> | boolean + isRead?: BoolFilter<"CachedEmail"> | boolean + isStarred?: BoolFilter<"CachedEmail"> | boolean + isDeleted?: BoolFilter<"CachedEmail"> | boolean + deletedAt?: DateTimeNullableFilter<"CachedEmail"> | Date | string | null + createdAt?: DateTimeFilter<"CachedEmail"> | Date | string + updatedAt?: DateTimeFilter<"CachedEmail"> | Date | string + } + + export type StressfreiEmailCreateWithoutCachedEmailsInput = { + email: string + platform?: string | null + notes?: string | null + isActive?: boolean + isProvisioned?: boolean + provisionedAt?: Date | string | null + provisionError?: string | null + hasMailbox?: boolean + emailPasswordEncrypted?: string | null + createdAt?: Date | string + updatedAt?: Date | string + customer: CustomerCreateNestedOneWithoutStressfreiEmailsInput + contracts?: ContractCreateNestedManyWithoutStressfreiEmailInput + } + + export type StressfreiEmailUncheckedCreateWithoutCachedEmailsInput = { + id?: number + customerId: number + email: string + platform?: string | null + notes?: string | null + isActive?: boolean + isProvisioned?: boolean + provisionedAt?: Date | string | null + provisionError?: string | null + hasMailbox?: boolean + emailPasswordEncrypted?: string | null + createdAt?: Date | string + updatedAt?: Date | string + contracts?: ContractUncheckedCreateNestedManyWithoutStressfreiEmailInput + } + + export type StressfreiEmailCreateOrConnectWithoutCachedEmailsInput = { + where: StressfreiEmailWhereUniqueInput + create: XOR + } + + export type ContractCreateWithoutAssignedEmailsInput = { + contractNumber: string + type: $Enums.ContractType + status?: $Enums.ContractStatus + providerName?: string | null + tariffName?: string | null + customerNumberAtProvider?: string | null + priceFirst12Months?: string | null + priceFrom13Months?: string | null + priceAfter24Months?: string | null + startDate?: Date | string | null + endDate?: Date | string | null + commission?: number | null + cancellationLetterPath?: string | null + cancellationConfirmationPath?: string | null + cancellationLetterOptionsPath?: string | null + cancellationConfirmationOptionsPath?: string | null + cancellationConfirmationDate?: Date | string | null + cancellationConfirmationOptionsDate?: Date | string | null + wasSpecialCancellation?: boolean + portalUsername?: string | null + portalPasswordEncrypted?: string | null + notes?: string | null + createdAt?: Date | string + updatedAt?: Date | string + customer: CustomerCreateNestedOneWithoutContractsInput + contractCategory?: ContractCategoryCreateNestedOneWithoutContractsInput + address?: AddressCreateNestedOneWithoutContractsInput + bankCard?: BankCardCreateNestedOneWithoutContractsInput + identityDocument?: IdentityDocumentCreateNestedOneWithoutContractsInput + salesPlatform?: SalesPlatformCreateNestedOneWithoutContractsInput + cancellationPeriod?: CancellationPeriodCreateNestedOneWithoutContractsInput + contractDuration?: ContractDurationCreateNestedOneWithoutContractsInput + previousContract?: ContractCreateNestedOneWithoutFollowUpContractInput + followUpContract?: ContractCreateNestedOneWithoutPreviousContractInput + provider?: ProviderCreateNestedOneWithoutContractsInput + tariff?: TariffCreateNestedOneWithoutContractsInput + stressfreiEmail?: StressfreiEmailCreateNestedOneWithoutContractsInput + energyDetails?: EnergyContractDetailsCreateNestedOneWithoutContractInput + internetDetails?: InternetContractDetailsCreateNestedOneWithoutContractInput + mobileDetails?: MobileContractDetailsCreateNestedOneWithoutContractInput + tvDetails?: TvContractDetailsCreateNestedOneWithoutContractInput + carInsuranceDetails?: CarInsuranceDetailsCreateNestedOneWithoutContractInput + tasks?: ContractTaskCreateNestedManyWithoutContractInput + } + + export type ContractUncheckedCreateWithoutAssignedEmailsInput = { + id?: number + contractNumber: string + customerId: number + type: $Enums.ContractType + status?: $Enums.ContractStatus + contractCategoryId?: number | null + addressId?: number | null + bankCardId?: number | null + identityDocumentId?: number | null + salesPlatformId?: number | null + cancellationPeriodId?: number | null + contractDurationId?: number | null + previousContractId?: number | null + providerId?: number | null + tariffId?: number | null + providerName?: string | null + tariffName?: string | null + customerNumberAtProvider?: string | null + priceFirst12Months?: string | null + priceFrom13Months?: string | null + priceAfter24Months?: string | null + startDate?: Date | string | null + endDate?: Date | string | null + commission?: number | null + cancellationLetterPath?: string | null + cancellationConfirmationPath?: string | null + cancellationLetterOptionsPath?: string | null + cancellationConfirmationOptionsPath?: string | null + cancellationConfirmationDate?: Date | string | null + cancellationConfirmationOptionsDate?: Date | string | null + wasSpecialCancellation?: boolean + portalUsername?: string | null + portalPasswordEncrypted?: string | null + stressfreiEmailId?: number | null + notes?: string | null + createdAt?: Date | string + updatedAt?: Date | string + followUpContract?: ContractUncheckedCreateNestedOneWithoutPreviousContractInput + energyDetails?: EnergyContractDetailsUncheckedCreateNestedOneWithoutContractInput + internetDetails?: InternetContractDetailsUncheckedCreateNestedOneWithoutContractInput + mobileDetails?: MobileContractDetailsUncheckedCreateNestedOneWithoutContractInput + tvDetails?: TvContractDetailsUncheckedCreateNestedOneWithoutContractInput + carInsuranceDetails?: CarInsuranceDetailsUncheckedCreateNestedOneWithoutContractInput + tasks?: ContractTaskUncheckedCreateNestedManyWithoutContractInput + } + + export type ContractCreateOrConnectWithoutAssignedEmailsInput = { + where: ContractWhereUniqueInput + create: XOR + } + + export type StressfreiEmailUpsertWithoutCachedEmailsInput = { + update: XOR + create: XOR + where?: StressfreiEmailWhereInput + } + + export type StressfreiEmailUpdateToOneWithWhereWithoutCachedEmailsInput = { + where?: StressfreiEmailWhereInput + data: XOR + } + + export type StressfreiEmailUpdateWithoutCachedEmailsInput = { + email?: StringFieldUpdateOperationsInput | string + platform?: NullableStringFieldUpdateOperationsInput | string | null + notes?: NullableStringFieldUpdateOperationsInput | string | null + isActive?: BoolFieldUpdateOperationsInput | boolean + isProvisioned?: BoolFieldUpdateOperationsInput | boolean + provisionedAt?: NullableDateTimeFieldUpdateOperationsInput | Date | string | null + provisionError?: NullableStringFieldUpdateOperationsInput | string | null + hasMailbox?: BoolFieldUpdateOperationsInput | boolean + emailPasswordEncrypted?: NullableStringFieldUpdateOperationsInput | string | null + createdAt?: DateTimeFieldUpdateOperationsInput | Date | string + updatedAt?: DateTimeFieldUpdateOperationsInput | Date | string + customer?: CustomerUpdateOneRequiredWithoutStressfreiEmailsNestedInput + contracts?: ContractUpdateManyWithoutStressfreiEmailNestedInput + } + + export type StressfreiEmailUncheckedUpdateWithoutCachedEmailsInput = { + id?: IntFieldUpdateOperationsInput | number + customerId?: IntFieldUpdateOperationsInput | number + email?: StringFieldUpdateOperationsInput | string + platform?: NullableStringFieldUpdateOperationsInput | string | null + notes?: NullableStringFieldUpdateOperationsInput | string | null + isActive?: BoolFieldUpdateOperationsInput | boolean + isProvisioned?: BoolFieldUpdateOperationsInput | boolean + provisionedAt?: NullableDateTimeFieldUpdateOperationsInput | Date | string | null + provisionError?: NullableStringFieldUpdateOperationsInput | string | null + hasMailbox?: BoolFieldUpdateOperationsInput | boolean + emailPasswordEncrypted?: NullableStringFieldUpdateOperationsInput | string | null + createdAt?: DateTimeFieldUpdateOperationsInput | Date | string + updatedAt?: DateTimeFieldUpdateOperationsInput | Date | string + contracts?: ContractUncheckedUpdateManyWithoutStressfreiEmailNestedInput + } + + export type ContractUpsertWithoutAssignedEmailsInput = { + update: XOR + create: XOR + where?: ContractWhereInput + } + + export type ContractUpdateToOneWithWhereWithoutAssignedEmailsInput = { + where?: ContractWhereInput + data: XOR + } + + export type ContractUpdateWithoutAssignedEmailsInput = { + contractNumber?: StringFieldUpdateOperationsInput | string + type?: EnumContractTypeFieldUpdateOperationsInput | $Enums.ContractType + status?: EnumContractStatusFieldUpdateOperationsInput | $Enums.ContractStatus + providerName?: NullableStringFieldUpdateOperationsInput | string | null + tariffName?: NullableStringFieldUpdateOperationsInput | string | null + customerNumberAtProvider?: NullableStringFieldUpdateOperationsInput | string | null + priceFirst12Months?: NullableStringFieldUpdateOperationsInput | string | null + priceFrom13Months?: NullableStringFieldUpdateOperationsInput | string | null + priceAfter24Months?: NullableStringFieldUpdateOperationsInput | string | null + startDate?: NullableDateTimeFieldUpdateOperationsInput | Date | string | null + endDate?: NullableDateTimeFieldUpdateOperationsInput | Date | string | null + commission?: NullableFloatFieldUpdateOperationsInput | number | null + cancellationLetterPath?: NullableStringFieldUpdateOperationsInput | string | null + cancellationConfirmationPath?: NullableStringFieldUpdateOperationsInput | string | null + cancellationLetterOptionsPath?: NullableStringFieldUpdateOperationsInput | string | null + cancellationConfirmationOptionsPath?: NullableStringFieldUpdateOperationsInput | string | null + cancellationConfirmationDate?: NullableDateTimeFieldUpdateOperationsInput | Date | string | null + cancellationConfirmationOptionsDate?: NullableDateTimeFieldUpdateOperationsInput | Date | string | null + wasSpecialCancellation?: BoolFieldUpdateOperationsInput | boolean + portalUsername?: NullableStringFieldUpdateOperationsInput | string | null + portalPasswordEncrypted?: NullableStringFieldUpdateOperationsInput | string | null + notes?: NullableStringFieldUpdateOperationsInput | string | null + createdAt?: DateTimeFieldUpdateOperationsInput | Date | string + updatedAt?: DateTimeFieldUpdateOperationsInput | Date | string + customer?: CustomerUpdateOneRequiredWithoutContractsNestedInput + contractCategory?: ContractCategoryUpdateOneWithoutContractsNestedInput + address?: AddressUpdateOneWithoutContractsNestedInput + bankCard?: BankCardUpdateOneWithoutContractsNestedInput + identityDocument?: IdentityDocumentUpdateOneWithoutContractsNestedInput + salesPlatform?: SalesPlatformUpdateOneWithoutContractsNestedInput + cancellationPeriod?: CancellationPeriodUpdateOneWithoutContractsNestedInput + contractDuration?: ContractDurationUpdateOneWithoutContractsNestedInput + previousContract?: ContractUpdateOneWithoutFollowUpContractNestedInput + followUpContract?: ContractUpdateOneWithoutPreviousContractNestedInput + provider?: ProviderUpdateOneWithoutContractsNestedInput + tariff?: TariffUpdateOneWithoutContractsNestedInput + stressfreiEmail?: StressfreiEmailUpdateOneWithoutContractsNestedInput + energyDetails?: EnergyContractDetailsUpdateOneWithoutContractNestedInput + internetDetails?: InternetContractDetailsUpdateOneWithoutContractNestedInput + mobileDetails?: MobileContractDetailsUpdateOneWithoutContractNestedInput + tvDetails?: TvContractDetailsUpdateOneWithoutContractNestedInput + carInsuranceDetails?: CarInsuranceDetailsUpdateOneWithoutContractNestedInput + tasks?: ContractTaskUpdateManyWithoutContractNestedInput + } + + export type ContractUncheckedUpdateWithoutAssignedEmailsInput = { + id?: IntFieldUpdateOperationsInput | number + contractNumber?: StringFieldUpdateOperationsInput | string + customerId?: IntFieldUpdateOperationsInput | number + type?: EnumContractTypeFieldUpdateOperationsInput | $Enums.ContractType + status?: EnumContractStatusFieldUpdateOperationsInput | $Enums.ContractStatus + contractCategoryId?: NullableIntFieldUpdateOperationsInput | number | null + addressId?: NullableIntFieldUpdateOperationsInput | number | null + bankCardId?: NullableIntFieldUpdateOperationsInput | number | null + identityDocumentId?: NullableIntFieldUpdateOperationsInput | number | null + salesPlatformId?: NullableIntFieldUpdateOperationsInput | number | null + cancellationPeriodId?: NullableIntFieldUpdateOperationsInput | number | null + contractDurationId?: NullableIntFieldUpdateOperationsInput | number | null + previousContractId?: NullableIntFieldUpdateOperationsInput | number | null + providerId?: NullableIntFieldUpdateOperationsInput | number | null + tariffId?: NullableIntFieldUpdateOperationsInput | number | null + providerName?: NullableStringFieldUpdateOperationsInput | string | null + tariffName?: NullableStringFieldUpdateOperationsInput | string | null + customerNumberAtProvider?: NullableStringFieldUpdateOperationsInput | string | null + priceFirst12Months?: NullableStringFieldUpdateOperationsInput | string | null + priceFrom13Months?: NullableStringFieldUpdateOperationsInput | string | null + priceAfter24Months?: NullableStringFieldUpdateOperationsInput | string | null + startDate?: NullableDateTimeFieldUpdateOperationsInput | Date | string | null + endDate?: NullableDateTimeFieldUpdateOperationsInput | Date | string | null + commission?: NullableFloatFieldUpdateOperationsInput | number | null + cancellationLetterPath?: NullableStringFieldUpdateOperationsInput | string | null + cancellationConfirmationPath?: NullableStringFieldUpdateOperationsInput | string | null + cancellationLetterOptionsPath?: NullableStringFieldUpdateOperationsInput | string | null + cancellationConfirmationOptionsPath?: NullableStringFieldUpdateOperationsInput | string | null + cancellationConfirmationDate?: NullableDateTimeFieldUpdateOperationsInput | Date | string | null + cancellationConfirmationOptionsDate?: NullableDateTimeFieldUpdateOperationsInput | Date | string | null + wasSpecialCancellation?: BoolFieldUpdateOperationsInput | boolean + portalUsername?: NullableStringFieldUpdateOperationsInput | string | null + portalPasswordEncrypted?: NullableStringFieldUpdateOperationsInput | string | null + stressfreiEmailId?: NullableIntFieldUpdateOperationsInput | number | null + notes?: NullableStringFieldUpdateOperationsInput | string | null + createdAt?: DateTimeFieldUpdateOperationsInput | Date | string + updatedAt?: DateTimeFieldUpdateOperationsInput | Date | string + followUpContract?: ContractUncheckedUpdateOneWithoutPreviousContractNestedInput + energyDetails?: EnergyContractDetailsUncheckedUpdateOneWithoutContractNestedInput + internetDetails?: InternetContractDetailsUncheckedUpdateOneWithoutContractNestedInput + mobileDetails?: MobileContractDetailsUncheckedUpdateOneWithoutContractNestedInput + tvDetails?: TvContractDetailsUncheckedUpdateOneWithoutContractNestedInput + carInsuranceDetails?: CarInsuranceDetailsUncheckedUpdateOneWithoutContractNestedInput + tasks?: ContractTaskUncheckedUpdateManyWithoutContractNestedInput + } + export type CustomerCreateWithoutMetersInput = { customerNumber: string type?: $Enums.CustomerType @@ -48770,6 +51535,7 @@ export namespace Prisma { tvDetails?: TvContractDetailsCreateNestedOneWithoutContractInput carInsuranceDetails?: CarInsuranceDetailsCreateNestedOneWithoutContractInput tasks?: ContractTaskCreateNestedManyWithoutContractInput + assignedEmails?: CachedEmailCreateNestedManyWithoutContractInput } export type ContractUncheckedCreateWithoutSalesPlatformInput = { @@ -48816,6 +51582,7 @@ export namespace Prisma { tvDetails?: TvContractDetailsUncheckedCreateNestedOneWithoutContractInput carInsuranceDetails?: CarInsuranceDetailsUncheckedCreateNestedOneWithoutContractInput tasks?: ContractTaskUncheckedCreateNestedManyWithoutContractInput + assignedEmails?: CachedEmailUncheckedCreateNestedManyWithoutContractInput } export type ContractCreateOrConnectWithoutSalesPlatformInput = { @@ -48887,6 +51654,7 @@ export namespace Prisma { tvDetails?: TvContractDetailsCreateNestedOneWithoutContractInput carInsuranceDetails?: CarInsuranceDetailsCreateNestedOneWithoutContractInput tasks?: ContractTaskCreateNestedManyWithoutContractInput + assignedEmails?: CachedEmailCreateNestedManyWithoutContractInput } export type ContractUncheckedCreateWithoutCancellationPeriodInput = { @@ -48933,6 +51701,7 @@ export namespace Prisma { tvDetails?: TvContractDetailsUncheckedCreateNestedOneWithoutContractInput carInsuranceDetails?: CarInsuranceDetailsUncheckedCreateNestedOneWithoutContractInput tasks?: ContractTaskUncheckedCreateNestedManyWithoutContractInput + assignedEmails?: CachedEmailUncheckedCreateNestedManyWithoutContractInput } export type ContractCreateOrConnectWithoutCancellationPeriodInput = { @@ -49004,6 +51773,7 @@ export namespace Prisma { tvDetails?: TvContractDetailsCreateNestedOneWithoutContractInput carInsuranceDetails?: CarInsuranceDetailsCreateNestedOneWithoutContractInput tasks?: ContractTaskCreateNestedManyWithoutContractInput + assignedEmails?: CachedEmailCreateNestedManyWithoutContractInput } export type ContractUncheckedCreateWithoutContractDurationInput = { @@ -49050,6 +51820,7 @@ export namespace Prisma { tvDetails?: TvContractDetailsUncheckedCreateNestedOneWithoutContractInput carInsuranceDetails?: CarInsuranceDetailsUncheckedCreateNestedOneWithoutContractInput tasks?: ContractTaskUncheckedCreateNestedManyWithoutContractInput + assignedEmails?: CachedEmailUncheckedCreateNestedManyWithoutContractInput } export type ContractCreateOrConnectWithoutContractDurationInput = { @@ -49148,6 +51919,7 @@ export namespace Prisma { tvDetails?: TvContractDetailsCreateNestedOneWithoutContractInput carInsuranceDetails?: CarInsuranceDetailsCreateNestedOneWithoutContractInput tasks?: ContractTaskCreateNestedManyWithoutContractInput + assignedEmails?: CachedEmailCreateNestedManyWithoutContractInput } export type ContractUncheckedCreateWithoutProviderInput = { @@ -49194,6 +51966,7 @@ export namespace Prisma { tvDetails?: TvContractDetailsUncheckedCreateNestedOneWithoutContractInput carInsuranceDetails?: CarInsuranceDetailsUncheckedCreateNestedOneWithoutContractInput tasks?: ContractTaskUncheckedCreateNestedManyWithoutContractInput + assignedEmails?: CachedEmailUncheckedCreateNestedManyWithoutContractInput } export type ContractCreateOrConnectWithoutProviderInput = { @@ -49321,6 +52094,7 @@ export namespace Prisma { tvDetails?: TvContractDetailsCreateNestedOneWithoutContractInput carInsuranceDetails?: CarInsuranceDetailsCreateNestedOneWithoutContractInput tasks?: ContractTaskCreateNestedManyWithoutContractInput + assignedEmails?: CachedEmailCreateNestedManyWithoutContractInput } export type ContractUncheckedCreateWithoutTariffInput = { @@ -49367,6 +52141,7 @@ export namespace Prisma { tvDetails?: TvContractDetailsUncheckedCreateNestedOneWithoutContractInput carInsuranceDetails?: CarInsuranceDetailsUncheckedCreateNestedOneWithoutContractInput tasks?: ContractTaskUncheckedCreateNestedManyWithoutContractInput + assignedEmails?: CachedEmailUncheckedCreateNestedManyWithoutContractInput } export type ContractCreateOrConnectWithoutTariffInput = { @@ -49472,6 +52247,7 @@ export namespace Prisma { tvDetails?: TvContractDetailsCreateNestedOneWithoutContractInput carInsuranceDetails?: CarInsuranceDetailsCreateNestedOneWithoutContractInput tasks?: ContractTaskCreateNestedManyWithoutContractInput + assignedEmails?: CachedEmailCreateNestedManyWithoutContractInput } export type ContractUncheckedCreateWithoutContractCategoryInput = { @@ -49518,6 +52294,7 @@ export namespace Prisma { tvDetails?: TvContractDetailsUncheckedCreateNestedOneWithoutContractInput carInsuranceDetails?: CarInsuranceDetailsUncheckedCreateNestedOneWithoutContractInput tasks?: ContractTaskUncheckedCreateNestedManyWithoutContractInput + assignedEmails?: CachedEmailUncheckedCreateNestedManyWithoutContractInput } export type ContractCreateOrConnectWithoutContractCategoryInput = { @@ -49861,6 +52638,7 @@ export namespace Prisma { tvDetails?: TvContractDetailsCreateNestedOneWithoutContractInput carInsuranceDetails?: CarInsuranceDetailsCreateNestedOneWithoutContractInput tasks?: ContractTaskCreateNestedManyWithoutContractInput + assignedEmails?: CachedEmailCreateNestedManyWithoutContractInput } export type ContractUncheckedCreateWithoutFollowUpContractInput = { @@ -49907,6 +52685,7 @@ export namespace Prisma { tvDetails?: TvContractDetailsUncheckedCreateNestedOneWithoutContractInput carInsuranceDetails?: CarInsuranceDetailsUncheckedCreateNestedOneWithoutContractInput tasks?: ContractTaskUncheckedCreateNestedManyWithoutContractInput + assignedEmails?: CachedEmailUncheckedCreateNestedManyWithoutContractInput } export type ContractCreateOrConnectWithoutFollowUpContractInput = { @@ -49957,6 +52736,7 @@ export namespace Prisma { tvDetails?: TvContractDetailsCreateNestedOneWithoutContractInput carInsuranceDetails?: CarInsuranceDetailsCreateNestedOneWithoutContractInput tasks?: ContractTaskCreateNestedManyWithoutContractInput + assignedEmails?: CachedEmailCreateNestedManyWithoutContractInput } export type ContractUncheckedCreateWithoutPreviousContractInput = { @@ -50003,6 +52783,7 @@ export namespace Prisma { tvDetails?: TvContractDetailsUncheckedCreateNestedOneWithoutContractInput carInsuranceDetails?: CarInsuranceDetailsUncheckedCreateNestedOneWithoutContractInput tasks?: ContractTaskUncheckedCreateNestedManyWithoutContractInput + assignedEmails?: CachedEmailUncheckedCreateNestedManyWithoutContractInput } export type ContractCreateOrConnectWithoutPreviousContractInput = { @@ -50068,9 +52849,12 @@ export namespace Prisma { isProvisioned?: boolean provisionedAt?: Date | string | null provisionError?: string | null + hasMailbox?: boolean + emailPasswordEncrypted?: string | null createdAt?: Date | string updatedAt?: Date | string customer: CustomerCreateNestedOneWithoutStressfreiEmailsInput + cachedEmails?: CachedEmailCreateNestedManyWithoutStressfreiEmailInput } export type StressfreiEmailUncheckedCreateWithoutContractsInput = { @@ -50083,8 +52867,11 @@ export namespace Prisma { isProvisioned?: boolean provisionedAt?: Date | string | null provisionError?: string | null + hasMailbox?: boolean + emailPasswordEncrypted?: string | null createdAt?: Date | string updatedAt?: Date | string + cachedEmails?: CachedEmailUncheckedCreateNestedManyWithoutStressfreiEmailInput } export type StressfreiEmailCreateOrConnectWithoutContractsInput = { @@ -50269,6 +53056,69 @@ export namespace Prisma { skipDuplicates?: boolean } + export type CachedEmailCreateWithoutContractInput = { + folder?: $Enums.EmailFolder + messageId: string + uid: number + subject?: string | null + fromAddress: string + fromName?: string | null + toAddresses: string + ccAddresses?: string | null + receivedAt: Date | string + textBody?: string | null + htmlBody?: string | null + hasAttachments?: boolean + attachmentNames?: string | null + assignedAt?: Date | string | null + assignedBy?: number | null + isAutoAssigned?: boolean + isRead?: boolean + isStarred?: boolean + isDeleted?: boolean + deletedAt?: Date | string | null + createdAt?: Date | string + updatedAt?: Date | string + stressfreiEmail: StressfreiEmailCreateNestedOneWithoutCachedEmailsInput + } + + export type CachedEmailUncheckedCreateWithoutContractInput = { + id?: number + stressfreiEmailId: number + folder?: $Enums.EmailFolder + messageId: string + uid: number + subject?: string | null + fromAddress: string + fromName?: string | null + toAddresses: string + ccAddresses?: string | null + receivedAt: Date | string + textBody?: string | null + htmlBody?: string | null + hasAttachments?: boolean + attachmentNames?: string | null + assignedAt?: Date | string | null + assignedBy?: number | null + isAutoAssigned?: boolean + isRead?: boolean + isStarred?: boolean + isDeleted?: boolean + deletedAt?: Date | string | null + createdAt?: Date | string + updatedAt?: Date | string + } + + export type CachedEmailCreateOrConnectWithoutContractInput = { + where: CachedEmailWhereUniqueInput + create: XOR + } + + export type CachedEmailCreateManyContractInputEnvelope = { + data: CachedEmailCreateManyContractInput | CachedEmailCreateManyContractInput[] + skipDuplicates?: boolean + } + export type CustomerUpsertWithoutContractsInput = { update: XOR create: XOR @@ -50643,6 +53493,7 @@ export namespace Prisma { tvDetails?: TvContractDetailsUpdateOneWithoutContractNestedInput carInsuranceDetails?: CarInsuranceDetailsUpdateOneWithoutContractNestedInput tasks?: ContractTaskUpdateManyWithoutContractNestedInput + assignedEmails?: CachedEmailUpdateManyWithoutContractNestedInput } export type ContractUncheckedUpdateWithoutFollowUpContractInput = { @@ -50689,6 +53540,7 @@ export namespace Prisma { tvDetails?: TvContractDetailsUncheckedUpdateOneWithoutContractNestedInput carInsuranceDetails?: CarInsuranceDetailsUncheckedUpdateOneWithoutContractNestedInput tasks?: ContractTaskUncheckedUpdateManyWithoutContractNestedInput + assignedEmails?: CachedEmailUncheckedUpdateManyWithoutContractNestedInput } export type ContractUpsertWithoutPreviousContractInput = { @@ -50745,6 +53597,7 @@ export namespace Prisma { tvDetails?: TvContractDetailsUpdateOneWithoutContractNestedInput carInsuranceDetails?: CarInsuranceDetailsUpdateOneWithoutContractNestedInput tasks?: ContractTaskUpdateManyWithoutContractNestedInput + assignedEmails?: CachedEmailUpdateManyWithoutContractNestedInput } export type ContractUncheckedUpdateWithoutPreviousContractInput = { @@ -50791,6 +53644,7 @@ export namespace Prisma { tvDetails?: TvContractDetailsUncheckedUpdateOneWithoutContractNestedInput carInsuranceDetails?: CarInsuranceDetailsUncheckedUpdateOneWithoutContractNestedInput tasks?: ContractTaskUncheckedUpdateManyWithoutContractNestedInput + assignedEmails?: CachedEmailUncheckedUpdateManyWithoutContractNestedInput } export type ProviderUpsertWithoutContractsInput = { @@ -50874,9 +53728,12 @@ export namespace Prisma { isProvisioned?: BoolFieldUpdateOperationsInput | boolean provisionedAt?: NullableDateTimeFieldUpdateOperationsInput | Date | string | null provisionError?: NullableStringFieldUpdateOperationsInput | string | null + hasMailbox?: BoolFieldUpdateOperationsInput | boolean + emailPasswordEncrypted?: NullableStringFieldUpdateOperationsInput | string | null createdAt?: DateTimeFieldUpdateOperationsInput | Date | string updatedAt?: DateTimeFieldUpdateOperationsInput | Date | string customer?: CustomerUpdateOneRequiredWithoutStressfreiEmailsNestedInput + cachedEmails?: CachedEmailUpdateManyWithoutStressfreiEmailNestedInput } export type StressfreiEmailUncheckedUpdateWithoutContractsInput = { @@ -50889,8 +53746,11 @@ export namespace Prisma { isProvisioned?: BoolFieldUpdateOperationsInput | boolean provisionedAt?: NullableDateTimeFieldUpdateOperationsInput | Date | string | null provisionError?: NullableStringFieldUpdateOperationsInput | string | null + hasMailbox?: BoolFieldUpdateOperationsInput | boolean + emailPasswordEncrypted?: NullableStringFieldUpdateOperationsInput | string | null createdAt?: DateTimeFieldUpdateOperationsInput | Date | string updatedAt?: DateTimeFieldUpdateOperationsInput | Date | string + cachedEmails?: CachedEmailUncheckedUpdateManyWithoutStressfreiEmailNestedInput } export type EnergyContractDetailsUpsertWithoutContractInput = { @@ -51097,6 +53957,22 @@ export namespace Prisma { updatedAt?: DateTimeFilter<"ContractTask"> | Date | string } + export type CachedEmailUpsertWithWhereUniqueWithoutContractInput = { + where: CachedEmailWhereUniqueInput + update: XOR + create: XOR + } + + export type CachedEmailUpdateWithWhereUniqueWithoutContractInput = { + where: CachedEmailWhereUniqueInput + data: XOR + } + + export type CachedEmailUpdateManyWithWhereWithoutContractInput = { + where: CachedEmailScalarWhereInput + data: XOR + } + export type ContractCreateWithoutTasksInput = { contractNumber: string type: $Enums.ContractType @@ -51140,6 +54016,7 @@ export namespace Prisma { mobileDetails?: MobileContractDetailsCreateNestedOneWithoutContractInput tvDetails?: TvContractDetailsCreateNestedOneWithoutContractInput carInsuranceDetails?: CarInsuranceDetailsCreateNestedOneWithoutContractInput + assignedEmails?: CachedEmailCreateNestedManyWithoutContractInput } export type ContractUncheckedCreateWithoutTasksInput = { @@ -51186,6 +54063,7 @@ export namespace Prisma { mobileDetails?: MobileContractDetailsUncheckedCreateNestedOneWithoutContractInput tvDetails?: TvContractDetailsUncheckedCreateNestedOneWithoutContractInput carInsuranceDetails?: CarInsuranceDetailsUncheckedCreateNestedOneWithoutContractInput + assignedEmails?: CachedEmailUncheckedCreateNestedManyWithoutContractInput } export type ContractCreateOrConnectWithoutTasksInput = { @@ -51276,6 +54154,7 @@ export namespace Prisma { mobileDetails?: MobileContractDetailsUpdateOneWithoutContractNestedInput tvDetails?: TvContractDetailsUpdateOneWithoutContractNestedInput carInsuranceDetails?: CarInsuranceDetailsUpdateOneWithoutContractNestedInput + assignedEmails?: CachedEmailUpdateManyWithoutContractNestedInput } export type ContractUncheckedUpdateWithoutTasksInput = { @@ -51322,6 +54201,7 @@ export namespace Prisma { mobileDetails?: MobileContractDetailsUncheckedUpdateOneWithoutContractNestedInput tvDetails?: TvContractDetailsUncheckedUpdateOneWithoutContractNestedInput carInsuranceDetails?: CarInsuranceDetailsUncheckedUpdateOneWithoutContractNestedInput + assignedEmails?: CachedEmailUncheckedUpdateManyWithoutContractNestedInput } export type ContractTaskSubtaskUpsertWithWhereUniqueWithoutTaskInput = { @@ -51463,6 +54343,7 @@ export namespace Prisma { tvDetails?: TvContractDetailsCreateNestedOneWithoutContractInput carInsuranceDetails?: CarInsuranceDetailsCreateNestedOneWithoutContractInput tasks?: ContractTaskCreateNestedManyWithoutContractInput + assignedEmails?: CachedEmailCreateNestedManyWithoutContractInput } export type ContractUncheckedCreateWithoutEnergyDetailsInput = { @@ -51509,6 +54390,7 @@ export namespace Prisma { tvDetails?: TvContractDetailsUncheckedCreateNestedOneWithoutContractInput carInsuranceDetails?: CarInsuranceDetailsUncheckedCreateNestedOneWithoutContractInput tasks?: ContractTaskUncheckedCreateNestedManyWithoutContractInput + assignedEmails?: CachedEmailUncheckedCreateNestedManyWithoutContractInput } export type ContractCreateOrConnectWithoutEnergyDetailsInput = { @@ -51598,6 +54480,7 @@ export namespace Prisma { tvDetails?: TvContractDetailsUpdateOneWithoutContractNestedInput carInsuranceDetails?: CarInsuranceDetailsUpdateOneWithoutContractNestedInput tasks?: ContractTaskUpdateManyWithoutContractNestedInput + assignedEmails?: CachedEmailUpdateManyWithoutContractNestedInput } export type ContractUncheckedUpdateWithoutEnergyDetailsInput = { @@ -51644,6 +54527,7 @@ export namespace Prisma { tvDetails?: TvContractDetailsUncheckedUpdateOneWithoutContractNestedInput carInsuranceDetails?: CarInsuranceDetailsUncheckedUpdateOneWithoutContractNestedInput tasks?: ContractTaskUncheckedUpdateManyWithoutContractNestedInput + assignedEmails?: CachedEmailUncheckedUpdateManyWithoutContractNestedInput } export type MeterUpsertWithoutEnergyDetailsInput = { @@ -51723,6 +54607,7 @@ export namespace Prisma { tvDetails?: TvContractDetailsCreateNestedOneWithoutContractInput carInsuranceDetails?: CarInsuranceDetailsCreateNestedOneWithoutContractInput tasks?: ContractTaskCreateNestedManyWithoutContractInput + assignedEmails?: CachedEmailCreateNestedManyWithoutContractInput } export type ContractUncheckedCreateWithoutInternetDetailsInput = { @@ -51769,6 +54654,7 @@ export namespace Prisma { tvDetails?: TvContractDetailsUncheckedCreateNestedOneWithoutContractInput carInsuranceDetails?: CarInsuranceDetailsUncheckedCreateNestedOneWithoutContractInput tasks?: ContractTaskUncheckedCreateNestedManyWithoutContractInput + assignedEmails?: CachedEmailUncheckedCreateNestedManyWithoutContractInput } export type ContractCreateOrConnectWithoutInternetDetailsInput = { @@ -51857,6 +54743,7 @@ export namespace Prisma { tvDetails?: TvContractDetailsUpdateOneWithoutContractNestedInput carInsuranceDetails?: CarInsuranceDetailsUpdateOneWithoutContractNestedInput tasks?: ContractTaskUpdateManyWithoutContractNestedInput + assignedEmails?: CachedEmailUpdateManyWithoutContractNestedInput } export type ContractUncheckedUpdateWithoutInternetDetailsInput = { @@ -51903,6 +54790,7 @@ export namespace Prisma { tvDetails?: TvContractDetailsUncheckedUpdateOneWithoutContractNestedInput carInsuranceDetails?: CarInsuranceDetailsUncheckedUpdateOneWithoutContractNestedInput tasks?: ContractTaskUncheckedUpdateManyWithoutContractNestedInput + assignedEmails?: CachedEmailUncheckedUpdateManyWithoutContractNestedInput } export type PhoneNumberUpsertWithWhereUniqueWithoutInternetDetailsInput = { @@ -52047,6 +54935,7 @@ export namespace Prisma { tvDetails?: TvContractDetailsCreateNestedOneWithoutContractInput carInsuranceDetails?: CarInsuranceDetailsCreateNestedOneWithoutContractInput tasks?: ContractTaskCreateNestedManyWithoutContractInput + assignedEmails?: CachedEmailCreateNestedManyWithoutContractInput } export type ContractUncheckedCreateWithoutMobileDetailsInput = { @@ -52093,6 +54982,7 @@ export namespace Prisma { tvDetails?: TvContractDetailsUncheckedCreateNestedOneWithoutContractInput carInsuranceDetails?: CarInsuranceDetailsUncheckedCreateNestedOneWithoutContractInput tasks?: ContractTaskUncheckedCreateNestedManyWithoutContractInput + assignedEmails?: CachedEmailUncheckedCreateNestedManyWithoutContractInput } export type ContractCreateOrConnectWithoutMobileDetailsInput = { @@ -52187,6 +55077,7 @@ export namespace Prisma { tvDetails?: TvContractDetailsUpdateOneWithoutContractNestedInput carInsuranceDetails?: CarInsuranceDetailsUpdateOneWithoutContractNestedInput tasks?: ContractTaskUpdateManyWithoutContractNestedInput + assignedEmails?: CachedEmailUpdateManyWithoutContractNestedInput } export type ContractUncheckedUpdateWithoutMobileDetailsInput = { @@ -52233,6 +55124,7 @@ export namespace Prisma { tvDetails?: TvContractDetailsUncheckedUpdateOneWithoutContractNestedInput carInsuranceDetails?: CarInsuranceDetailsUncheckedUpdateOneWithoutContractNestedInput tasks?: ContractTaskUncheckedUpdateManyWithoutContractNestedInput + assignedEmails?: CachedEmailUncheckedUpdateManyWithoutContractNestedInput } export type SimCardUpsertWithWhereUniqueWithoutMobileDetailsInput = { @@ -52376,6 +55268,7 @@ export namespace Prisma { mobileDetails?: MobileContractDetailsCreateNestedOneWithoutContractInput carInsuranceDetails?: CarInsuranceDetailsCreateNestedOneWithoutContractInput tasks?: ContractTaskCreateNestedManyWithoutContractInput + assignedEmails?: CachedEmailCreateNestedManyWithoutContractInput } export type ContractUncheckedCreateWithoutTvDetailsInput = { @@ -52422,6 +55315,7 @@ export namespace Prisma { mobileDetails?: MobileContractDetailsUncheckedCreateNestedOneWithoutContractInput carInsuranceDetails?: CarInsuranceDetailsUncheckedCreateNestedOneWithoutContractInput tasks?: ContractTaskUncheckedCreateNestedManyWithoutContractInput + assignedEmails?: CachedEmailUncheckedCreateNestedManyWithoutContractInput } export type ContractCreateOrConnectWithoutTvDetailsInput = { @@ -52483,6 +55377,7 @@ export namespace Prisma { mobileDetails?: MobileContractDetailsUpdateOneWithoutContractNestedInput carInsuranceDetails?: CarInsuranceDetailsUpdateOneWithoutContractNestedInput tasks?: ContractTaskUpdateManyWithoutContractNestedInput + assignedEmails?: CachedEmailUpdateManyWithoutContractNestedInput } export type ContractUncheckedUpdateWithoutTvDetailsInput = { @@ -52529,6 +55424,7 @@ export namespace Prisma { mobileDetails?: MobileContractDetailsUncheckedUpdateOneWithoutContractNestedInput carInsuranceDetails?: CarInsuranceDetailsUncheckedUpdateOneWithoutContractNestedInput tasks?: ContractTaskUncheckedUpdateManyWithoutContractNestedInput + assignedEmails?: CachedEmailUncheckedUpdateManyWithoutContractNestedInput } export type ContractCreateWithoutCarInsuranceDetailsInput = { @@ -52574,6 +55470,7 @@ export namespace Prisma { mobileDetails?: MobileContractDetailsCreateNestedOneWithoutContractInput tvDetails?: TvContractDetailsCreateNestedOneWithoutContractInput tasks?: ContractTaskCreateNestedManyWithoutContractInput + assignedEmails?: CachedEmailCreateNestedManyWithoutContractInput } export type ContractUncheckedCreateWithoutCarInsuranceDetailsInput = { @@ -52620,6 +55517,7 @@ export namespace Prisma { mobileDetails?: MobileContractDetailsUncheckedCreateNestedOneWithoutContractInput tvDetails?: TvContractDetailsUncheckedCreateNestedOneWithoutContractInput tasks?: ContractTaskUncheckedCreateNestedManyWithoutContractInput + assignedEmails?: CachedEmailUncheckedCreateNestedManyWithoutContractInput } export type ContractCreateOrConnectWithoutCarInsuranceDetailsInput = { @@ -52681,6 +55579,7 @@ export namespace Prisma { mobileDetails?: MobileContractDetailsUpdateOneWithoutContractNestedInput tvDetails?: TvContractDetailsUpdateOneWithoutContractNestedInput tasks?: ContractTaskUpdateManyWithoutContractNestedInput + assignedEmails?: CachedEmailUpdateManyWithoutContractNestedInput } export type ContractUncheckedUpdateWithoutCarInsuranceDetailsInput = { @@ -52727,6 +55626,7 @@ export namespace Prisma { mobileDetails?: MobileContractDetailsUncheckedUpdateOneWithoutContractNestedInput tvDetails?: TvContractDetailsUncheckedUpdateOneWithoutContractNestedInput tasks?: ContractTaskUncheckedUpdateManyWithoutContractNestedInput + assignedEmails?: CachedEmailUncheckedUpdateManyWithoutContractNestedInput } export type UserRoleCreateManyUserInput = { @@ -52853,6 +55753,8 @@ export namespace Prisma { isProvisioned?: boolean provisionedAt?: Date | string | null provisionError?: string | null + hasMailbox?: boolean + emailPasswordEncrypted?: string | null createdAt?: Date | string updatedAt?: Date | string } @@ -53081,9 +55983,12 @@ export namespace Prisma { isProvisioned?: BoolFieldUpdateOperationsInput | boolean provisionedAt?: NullableDateTimeFieldUpdateOperationsInput | Date | string | null provisionError?: NullableStringFieldUpdateOperationsInput | string | null + hasMailbox?: BoolFieldUpdateOperationsInput | boolean + emailPasswordEncrypted?: NullableStringFieldUpdateOperationsInput | string | null createdAt?: DateTimeFieldUpdateOperationsInput | Date | string updatedAt?: DateTimeFieldUpdateOperationsInput | Date | string contracts?: ContractUpdateManyWithoutStressfreiEmailNestedInput + cachedEmails?: CachedEmailUpdateManyWithoutStressfreiEmailNestedInput } export type StressfreiEmailUncheckedUpdateWithoutCustomerInput = { @@ -53095,9 +56000,12 @@ export namespace Prisma { isProvisioned?: BoolFieldUpdateOperationsInput | boolean provisionedAt?: NullableDateTimeFieldUpdateOperationsInput | Date | string | null provisionError?: NullableStringFieldUpdateOperationsInput | string | null + hasMailbox?: BoolFieldUpdateOperationsInput | boolean + emailPasswordEncrypted?: NullableStringFieldUpdateOperationsInput | string | null createdAt?: DateTimeFieldUpdateOperationsInput | Date | string updatedAt?: DateTimeFieldUpdateOperationsInput | Date | string contracts?: ContractUncheckedUpdateManyWithoutStressfreiEmailNestedInput + cachedEmails?: CachedEmailUncheckedUpdateManyWithoutStressfreiEmailNestedInput } export type StressfreiEmailUncheckedUpdateManyWithoutCustomerInput = { @@ -53109,6 +56017,8 @@ export namespace Prisma { isProvisioned?: BoolFieldUpdateOperationsInput | boolean provisionedAt?: NullableDateTimeFieldUpdateOperationsInput | Date | string | null provisionError?: NullableStringFieldUpdateOperationsInput | string | null + hasMailbox?: BoolFieldUpdateOperationsInput | boolean + emailPasswordEncrypted?: NullableStringFieldUpdateOperationsInput | string | null createdAt?: DateTimeFieldUpdateOperationsInput | Date | string updatedAt?: DateTimeFieldUpdateOperationsInput | Date | string } @@ -53156,6 +56066,7 @@ export namespace Prisma { tvDetails?: TvContractDetailsUpdateOneWithoutContractNestedInput carInsuranceDetails?: CarInsuranceDetailsUpdateOneWithoutContractNestedInput tasks?: ContractTaskUpdateManyWithoutContractNestedInput + assignedEmails?: CachedEmailUpdateManyWithoutContractNestedInput } export type ContractUncheckedUpdateWithoutCustomerInput = { @@ -53202,6 +56113,7 @@ export namespace Prisma { tvDetails?: TvContractDetailsUncheckedUpdateOneWithoutContractNestedInput carInsuranceDetails?: CarInsuranceDetailsUncheckedUpdateOneWithoutContractNestedInput tasks?: ContractTaskUncheckedUpdateManyWithoutContractNestedInput + assignedEmails?: CachedEmailUncheckedUpdateManyWithoutContractNestedInput } export type ContractUncheckedUpdateManyWithoutCustomerInput = { @@ -53377,6 +56289,7 @@ export namespace Prisma { tvDetails?: TvContractDetailsUpdateOneWithoutContractNestedInput carInsuranceDetails?: CarInsuranceDetailsUpdateOneWithoutContractNestedInput tasks?: ContractTaskUpdateManyWithoutContractNestedInput + assignedEmails?: CachedEmailUpdateManyWithoutContractNestedInput } export type ContractUncheckedUpdateWithoutAddressInput = { @@ -53423,6 +56336,7 @@ export namespace Prisma { tvDetails?: TvContractDetailsUncheckedUpdateOneWithoutContractNestedInput carInsuranceDetails?: CarInsuranceDetailsUncheckedUpdateOneWithoutContractNestedInput tasks?: ContractTaskUncheckedUpdateManyWithoutContractNestedInput + assignedEmails?: CachedEmailUncheckedUpdateManyWithoutContractNestedInput } export type ContractUncheckedUpdateManyWithoutAddressInput = { @@ -53546,6 +56460,7 @@ export namespace Prisma { tvDetails?: TvContractDetailsUpdateOneWithoutContractNestedInput carInsuranceDetails?: CarInsuranceDetailsUpdateOneWithoutContractNestedInput tasks?: ContractTaskUpdateManyWithoutContractNestedInput + assignedEmails?: CachedEmailUpdateManyWithoutContractNestedInput } export type ContractUncheckedUpdateWithoutBankCardInput = { @@ -53592,6 +56507,7 @@ export namespace Prisma { tvDetails?: TvContractDetailsUncheckedUpdateOneWithoutContractNestedInput carInsuranceDetails?: CarInsuranceDetailsUncheckedUpdateOneWithoutContractNestedInput tasks?: ContractTaskUncheckedUpdateManyWithoutContractNestedInput + assignedEmails?: CachedEmailUncheckedUpdateManyWithoutContractNestedInput } export type ContractUncheckedUpdateManyWithoutBankCardInput = { @@ -53715,6 +56631,7 @@ export namespace Prisma { tvDetails?: TvContractDetailsUpdateOneWithoutContractNestedInput carInsuranceDetails?: CarInsuranceDetailsUpdateOneWithoutContractNestedInput tasks?: ContractTaskUpdateManyWithoutContractNestedInput + assignedEmails?: CachedEmailUpdateManyWithoutContractNestedInput } export type ContractUncheckedUpdateWithoutIdentityDocumentInput = { @@ -53761,6 +56678,7 @@ export namespace Prisma { tvDetails?: TvContractDetailsUncheckedUpdateOneWithoutContractNestedInput carInsuranceDetails?: CarInsuranceDetailsUncheckedUpdateOneWithoutContractNestedInput tasks?: ContractTaskUncheckedUpdateManyWithoutContractNestedInput + assignedEmails?: CachedEmailUncheckedUpdateManyWithoutContractNestedInput } export type ContractUncheckedUpdateManyWithoutIdentityDocumentInput = { @@ -53841,6 +56759,33 @@ export namespace Prisma { updatedAt?: Date | string } + export type CachedEmailCreateManyStressfreiEmailInput = { + id?: number + folder?: $Enums.EmailFolder + messageId: string + uid: number + subject?: string | null + fromAddress: string + fromName?: string | null + toAddresses: string + ccAddresses?: string | null + receivedAt: Date | string + textBody?: string | null + htmlBody?: string | null + hasAttachments?: boolean + attachmentNames?: string | null + contractId?: number | null + assignedAt?: Date | string | null + assignedBy?: number | null + isAutoAssigned?: boolean + isRead?: boolean + isStarred?: boolean + isDeleted?: boolean + deletedAt?: Date | string | null + createdAt?: Date | string + updatedAt?: Date | string + } + export type ContractUpdateWithoutStressfreiEmailInput = { contractNumber?: StringFieldUpdateOperationsInput | string type?: EnumContractTypeFieldUpdateOperationsInput | $Enums.ContractType @@ -53884,6 +56829,7 @@ export namespace Prisma { tvDetails?: TvContractDetailsUpdateOneWithoutContractNestedInput carInsuranceDetails?: CarInsuranceDetailsUpdateOneWithoutContractNestedInput tasks?: ContractTaskUpdateManyWithoutContractNestedInput + assignedEmails?: CachedEmailUpdateManyWithoutContractNestedInput } export type ContractUncheckedUpdateWithoutStressfreiEmailInput = { @@ -53930,6 +56876,7 @@ export namespace Prisma { tvDetails?: TvContractDetailsUncheckedUpdateOneWithoutContractNestedInput carInsuranceDetails?: CarInsuranceDetailsUncheckedUpdateOneWithoutContractNestedInput tasks?: ContractTaskUncheckedUpdateManyWithoutContractNestedInput + assignedEmails?: CachedEmailUncheckedUpdateManyWithoutContractNestedInput } export type ContractUncheckedUpdateManyWithoutStressfreiEmailInput = { @@ -53971,6 +56918,86 @@ export namespace Prisma { updatedAt?: DateTimeFieldUpdateOperationsInput | Date | string } + export type CachedEmailUpdateWithoutStressfreiEmailInput = { + folder?: EnumEmailFolderFieldUpdateOperationsInput | $Enums.EmailFolder + messageId?: StringFieldUpdateOperationsInput | string + uid?: IntFieldUpdateOperationsInput | number + subject?: NullableStringFieldUpdateOperationsInput | string | null + fromAddress?: StringFieldUpdateOperationsInput | string + fromName?: NullableStringFieldUpdateOperationsInput | string | null + toAddresses?: StringFieldUpdateOperationsInput | string + ccAddresses?: NullableStringFieldUpdateOperationsInput | string | null + receivedAt?: DateTimeFieldUpdateOperationsInput | Date | string + textBody?: NullableStringFieldUpdateOperationsInput | string | null + htmlBody?: NullableStringFieldUpdateOperationsInput | string | null + hasAttachments?: BoolFieldUpdateOperationsInput | boolean + attachmentNames?: NullableStringFieldUpdateOperationsInput | string | null + assignedAt?: NullableDateTimeFieldUpdateOperationsInput | Date | string | null + assignedBy?: NullableIntFieldUpdateOperationsInput | number | null + isAutoAssigned?: BoolFieldUpdateOperationsInput | boolean + isRead?: BoolFieldUpdateOperationsInput | boolean + isStarred?: BoolFieldUpdateOperationsInput | boolean + isDeleted?: BoolFieldUpdateOperationsInput | boolean + deletedAt?: NullableDateTimeFieldUpdateOperationsInput | Date | string | null + createdAt?: DateTimeFieldUpdateOperationsInput | Date | string + updatedAt?: DateTimeFieldUpdateOperationsInput | Date | string + contract?: ContractUpdateOneWithoutAssignedEmailsNestedInput + } + + export type CachedEmailUncheckedUpdateWithoutStressfreiEmailInput = { + id?: IntFieldUpdateOperationsInput | number + folder?: EnumEmailFolderFieldUpdateOperationsInput | $Enums.EmailFolder + messageId?: StringFieldUpdateOperationsInput | string + uid?: IntFieldUpdateOperationsInput | number + subject?: NullableStringFieldUpdateOperationsInput | string | null + fromAddress?: StringFieldUpdateOperationsInput | string + fromName?: NullableStringFieldUpdateOperationsInput | string | null + toAddresses?: StringFieldUpdateOperationsInput | string + ccAddresses?: NullableStringFieldUpdateOperationsInput | string | null + receivedAt?: DateTimeFieldUpdateOperationsInput | Date | string + textBody?: NullableStringFieldUpdateOperationsInput | string | null + htmlBody?: NullableStringFieldUpdateOperationsInput | string | null + hasAttachments?: BoolFieldUpdateOperationsInput | boolean + attachmentNames?: NullableStringFieldUpdateOperationsInput | string | null + contractId?: NullableIntFieldUpdateOperationsInput | number | null + assignedAt?: NullableDateTimeFieldUpdateOperationsInput | Date | string | null + assignedBy?: NullableIntFieldUpdateOperationsInput | number | null + isAutoAssigned?: BoolFieldUpdateOperationsInput | boolean + isRead?: BoolFieldUpdateOperationsInput | boolean + isStarred?: BoolFieldUpdateOperationsInput | boolean + isDeleted?: BoolFieldUpdateOperationsInput | boolean + deletedAt?: NullableDateTimeFieldUpdateOperationsInput | Date | string | null + createdAt?: DateTimeFieldUpdateOperationsInput | Date | string + updatedAt?: DateTimeFieldUpdateOperationsInput | Date | string + } + + export type CachedEmailUncheckedUpdateManyWithoutStressfreiEmailInput = { + id?: IntFieldUpdateOperationsInput | number + folder?: EnumEmailFolderFieldUpdateOperationsInput | $Enums.EmailFolder + messageId?: StringFieldUpdateOperationsInput | string + uid?: IntFieldUpdateOperationsInput | number + subject?: NullableStringFieldUpdateOperationsInput | string | null + fromAddress?: StringFieldUpdateOperationsInput | string + fromName?: NullableStringFieldUpdateOperationsInput | string | null + toAddresses?: StringFieldUpdateOperationsInput | string + ccAddresses?: NullableStringFieldUpdateOperationsInput | string | null + receivedAt?: DateTimeFieldUpdateOperationsInput | Date | string + textBody?: NullableStringFieldUpdateOperationsInput | string | null + htmlBody?: NullableStringFieldUpdateOperationsInput | string | null + hasAttachments?: BoolFieldUpdateOperationsInput | boolean + attachmentNames?: NullableStringFieldUpdateOperationsInput | string | null + contractId?: NullableIntFieldUpdateOperationsInput | number | null + assignedAt?: NullableDateTimeFieldUpdateOperationsInput | Date | string | null + assignedBy?: NullableIntFieldUpdateOperationsInput | number | null + isAutoAssigned?: BoolFieldUpdateOperationsInput | boolean + isRead?: BoolFieldUpdateOperationsInput | boolean + isStarred?: BoolFieldUpdateOperationsInput | boolean + isDeleted?: BoolFieldUpdateOperationsInput | boolean + deletedAt?: NullableDateTimeFieldUpdateOperationsInput | Date | string | null + createdAt?: DateTimeFieldUpdateOperationsInput | Date | string + updatedAt?: DateTimeFieldUpdateOperationsInput | Date | string + } + export type MeterReadingCreateManyMeterInput = { id?: number readingDate: Date | string @@ -54131,6 +57158,7 @@ export namespace Prisma { tvDetails?: TvContractDetailsUpdateOneWithoutContractNestedInput carInsuranceDetails?: CarInsuranceDetailsUpdateOneWithoutContractNestedInput tasks?: ContractTaskUpdateManyWithoutContractNestedInput + assignedEmails?: CachedEmailUpdateManyWithoutContractNestedInput } export type ContractUncheckedUpdateWithoutSalesPlatformInput = { @@ -54177,6 +57205,7 @@ export namespace Prisma { tvDetails?: TvContractDetailsUncheckedUpdateOneWithoutContractNestedInput carInsuranceDetails?: CarInsuranceDetailsUncheckedUpdateOneWithoutContractNestedInput tasks?: ContractTaskUncheckedUpdateManyWithoutContractNestedInput + assignedEmails?: CachedEmailUncheckedUpdateManyWithoutContractNestedInput } export type ContractUncheckedUpdateManyWithoutSalesPlatformInput = { @@ -54300,6 +57329,7 @@ export namespace Prisma { tvDetails?: TvContractDetailsUpdateOneWithoutContractNestedInput carInsuranceDetails?: CarInsuranceDetailsUpdateOneWithoutContractNestedInput tasks?: ContractTaskUpdateManyWithoutContractNestedInput + assignedEmails?: CachedEmailUpdateManyWithoutContractNestedInput } export type ContractUncheckedUpdateWithoutCancellationPeriodInput = { @@ -54346,6 +57376,7 @@ export namespace Prisma { tvDetails?: TvContractDetailsUncheckedUpdateOneWithoutContractNestedInput carInsuranceDetails?: CarInsuranceDetailsUncheckedUpdateOneWithoutContractNestedInput tasks?: ContractTaskUncheckedUpdateManyWithoutContractNestedInput + assignedEmails?: CachedEmailUncheckedUpdateManyWithoutContractNestedInput } export type ContractUncheckedUpdateManyWithoutCancellationPeriodInput = { @@ -54469,6 +57500,7 @@ export namespace Prisma { tvDetails?: TvContractDetailsUpdateOneWithoutContractNestedInput carInsuranceDetails?: CarInsuranceDetailsUpdateOneWithoutContractNestedInput tasks?: ContractTaskUpdateManyWithoutContractNestedInput + assignedEmails?: CachedEmailUpdateManyWithoutContractNestedInput } export type ContractUncheckedUpdateWithoutContractDurationInput = { @@ -54515,6 +57547,7 @@ export namespace Prisma { tvDetails?: TvContractDetailsUncheckedUpdateOneWithoutContractNestedInput carInsuranceDetails?: CarInsuranceDetailsUncheckedUpdateOneWithoutContractNestedInput tasks?: ContractTaskUncheckedUpdateManyWithoutContractNestedInput + assignedEmails?: CachedEmailUncheckedUpdateManyWithoutContractNestedInput } export type ContractUncheckedUpdateManyWithoutContractDurationInput = { @@ -54671,6 +57704,7 @@ export namespace Prisma { tvDetails?: TvContractDetailsUpdateOneWithoutContractNestedInput carInsuranceDetails?: CarInsuranceDetailsUpdateOneWithoutContractNestedInput tasks?: ContractTaskUpdateManyWithoutContractNestedInput + assignedEmails?: CachedEmailUpdateManyWithoutContractNestedInput } export type ContractUncheckedUpdateWithoutProviderInput = { @@ -54717,6 +57751,7 @@ export namespace Prisma { tvDetails?: TvContractDetailsUncheckedUpdateOneWithoutContractNestedInput carInsuranceDetails?: CarInsuranceDetailsUncheckedUpdateOneWithoutContractNestedInput tasks?: ContractTaskUncheckedUpdateManyWithoutContractNestedInput + assignedEmails?: CachedEmailUncheckedUpdateManyWithoutContractNestedInput } export type ContractUncheckedUpdateManyWithoutProviderInput = { @@ -54840,6 +57875,7 @@ export namespace Prisma { tvDetails?: TvContractDetailsUpdateOneWithoutContractNestedInput carInsuranceDetails?: CarInsuranceDetailsUpdateOneWithoutContractNestedInput tasks?: ContractTaskUpdateManyWithoutContractNestedInput + assignedEmails?: CachedEmailUpdateManyWithoutContractNestedInput } export type ContractUncheckedUpdateWithoutTariffInput = { @@ -54886,6 +57922,7 @@ export namespace Prisma { tvDetails?: TvContractDetailsUncheckedUpdateOneWithoutContractNestedInput carInsuranceDetails?: CarInsuranceDetailsUncheckedUpdateOneWithoutContractNestedInput tasks?: ContractTaskUncheckedUpdateManyWithoutContractNestedInput + assignedEmails?: CachedEmailUncheckedUpdateManyWithoutContractNestedInput } export type ContractUncheckedUpdateManyWithoutTariffInput = { @@ -55009,6 +58046,7 @@ export namespace Prisma { tvDetails?: TvContractDetailsUpdateOneWithoutContractNestedInput carInsuranceDetails?: CarInsuranceDetailsUpdateOneWithoutContractNestedInput tasks?: ContractTaskUpdateManyWithoutContractNestedInput + assignedEmails?: CachedEmailUpdateManyWithoutContractNestedInput } export type ContractUncheckedUpdateWithoutContractCategoryInput = { @@ -55055,6 +58093,7 @@ export namespace Prisma { tvDetails?: TvContractDetailsUncheckedUpdateOneWithoutContractNestedInput carInsuranceDetails?: CarInsuranceDetailsUncheckedUpdateOneWithoutContractNestedInput tasks?: ContractTaskUncheckedUpdateManyWithoutContractNestedInput + assignedEmails?: CachedEmailUncheckedUpdateManyWithoutContractNestedInput } export type ContractUncheckedUpdateManyWithoutContractCategoryInput = { @@ -55108,6 +58147,33 @@ export namespace Prisma { updatedAt?: Date | string } + export type CachedEmailCreateManyContractInput = { + id?: number + stressfreiEmailId: number + folder?: $Enums.EmailFolder + messageId: string + uid: number + subject?: string | null + fromAddress: string + fromName?: string | null + toAddresses: string + ccAddresses?: string | null + receivedAt: Date | string + textBody?: string | null + htmlBody?: string | null + hasAttachments?: boolean + attachmentNames?: string | null + assignedAt?: Date | string | null + assignedBy?: number | null + isAutoAssigned?: boolean + isRead?: boolean + isStarred?: boolean + isDeleted?: boolean + deletedAt?: Date | string | null + createdAt?: Date | string + updatedAt?: Date | string + } + export type ContractTaskUpdateWithoutContractInput = { title?: StringFieldUpdateOperationsInput | string description?: NullableStringFieldUpdateOperationsInput | string | null @@ -55145,6 +58211,86 @@ export namespace Prisma { updatedAt?: DateTimeFieldUpdateOperationsInput | Date | string } + export type CachedEmailUpdateWithoutContractInput = { + folder?: EnumEmailFolderFieldUpdateOperationsInput | $Enums.EmailFolder + messageId?: StringFieldUpdateOperationsInput | string + uid?: IntFieldUpdateOperationsInput | number + subject?: NullableStringFieldUpdateOperationsInput | string | null + fromAddress?: StringFieldUpdateOperationsInput | string + fromName?: NullableStringFieldUpdateOperationsInput | string | null + toAddresses?: StringFieldUpdateOperationsInput | string + ccAddresses?: NullableStringFieldUpdateOperationsInput | string | null + receivedAt?: DateTimeFieldUpdateOperationsInput | Date | string + textBody?: NullableStringFieldUpdateOperationsInput | string | null + htmlBody?: NullableStringFieldUpdateOperationsInput | string | null + hasAttachments?: BoolFieldUpdateOperationsInput | boolean + attachmentNames?: NullableStringFieldUpdateOperationsInput | string | null + assignedAt?: NullableDateTimeFieldUpdateOperationsInput | Date | string | null + assignedBy?: NullableIntFieldUpdateOperationsInput | number | null + isAutoAssigned?: BoolFieldUpdateOperationsInput | boolean + isRead?: BoolFieldUpdateOperationsInput | boolean + isStarred?: BoolFieldUpdateOperationsInput | boolean + isDeleted?: BoolFieldUpdateOperationsInput | boolean + deletedAt?: NullableDateTimeFieldUpdateOperationsInput | Date | string | null + createdAt?: DateTimeFieldUpdateOperationsInput | Date | string + updatedAt?: DateTimeFieldUpdateOperationsInput | Date | string + stressfreiEmail?: StressfreiEmailUpdateOneRequiredWithoutCachedEmailsNestedInput + } + + export type CachedEmailUncheckedUpdateWithoutContractInput = { + id?: IntFieldUpdateOperationsInput | number + stressfreiEmailId?: IntFieldUpdateOperationsInput | number + folder?: EnumEmailFolderFieldUpdateOperationsInput | $Enums.EmailFolder + messageId?: StringFieldUpdateOperationsInput | string + uid?: IntFieldUpdateOperationsInput | number + subject?: NullableStringFieldUpdateOperationsInput | string | null + fromAddress?: StringFieldUpdateOperationsInput | string + fromName?: NullableStringFieldUpdateOperationsInput | string | null + toAddresses?: StringFieldUpdateOperationsInput | string + ccAddresses?: NullableStringFieldUpdateOperationsInput | string | null + receivedAt?: DateTimeFieldUpdateOperationsInput | Date | string + textBody?: NullableStringFieldUpdateOperationsInput | string | null + htmlBody?: NullableStringFieldUpdateOperationsInput | string | null + hasAttachments?: BoolFieldUpdateOperationsInput | boolean + attachmentNames?: NullableStringFieldUpdateOperationsInput | string | null + assignedAt?: NullableDateTimeFieldUpdateOperationsInput | Date | string | null + assignedBy?: NullableIntFieldUpdateOperationsInput | number | null + isAutoAssigned?: BoolFieldUpdateOperationsInput | boolean + isRead?: BoolFieldUpdateOperationsInput | boolean + isStarred?: BoolFieldUpdateOperationsInput | boolean + isDeleted?: BoolFieldUpdateOperationsInput | boolean + deletedAt?: NullableDateTimeFieldUpdateOperationsInput | Date | string | null + createdAt?: DateTimeFieldUpdateOperationsInput | Date | string + updatedAt?: DateTimeFieldUpdateOperationsInput | Date | string + } + + export type CachedEmailUncheckedUpdateManyWithoutContractInput = { + id?: IntFieldUpdateOperationsInput | number + stressfreiEmailId?: IntFieldUpdateOperationsInput | number + folder?: EnumEmailFolderFieldUpdateOperationsInput | $Enums.EmailFolder + messageId?: StringFieldUpdateOperationsInput | string + uid?: IntFieldUpdateOperationsInput | number + subject?: NullableStringFieldUpdateOperationsInput | string | null + fromAddress?: StringFieldUpdateOperationsInput | string + fromName?: NullableStringFieldUpdateOperationsInput | string | null + toAddresses?: StringFieldUpdateOperationsInput | string + ccAddresses?: NullableStringFieldUpdateOperationsInput | string | null + receivedAt?: DateTimeFieldUpdateOperationsInput | Date | string + textBody?: NullableStringFieldUpdateOperationsInput | string | null + htmlBody?: NullableStringFieldUpdateOperationsInput | string | null + hasAttachments?: BoolFieldUpdateOperationsInput | boolean + attachmentNames?: NullableStringFieldUpdateOperationsInput | string | null + assignedAt?: NullableDateTimeFieldUpdateOperationsInput | Date | string | null + assignedBy?: NullableIntFieldUpdateOperationsInput | number | null + isAutoAssigned?: BoolFieldUpdateOperationsInput | boolean + isRead?: BoolFieldUpdateOperationsInput | boolean + isStarred?: BoolFieldUpdateOperationsInput | boolean + isDeleted?: BoolFieldUpdateOperationsInput | boolean + deletedAt?: NullableDateTimeFieldUpdateOperationsInput | Date | string | null + createdAt?: DateTimeFieldUpdateOperationsInput | Date | string + updatedAt?: DateTimeFieldUpdateOperationsInput | Date | string + } + export type ContractTaskSubtaskCreateManyTaskInput = { id?: number title: string @@ -55399,6 +58545,10 @@ export namespace Prisma { * @deprecated Use StressfreiEmailDefaultArgs instead */ export type StressfreiEmailArgs = StressfreiEmailDefaultArgs + /** + * @deprecated Use CachedEmailDefaultArgs instead + */ + export type CachedEmailArgs = CachedEmailDefaultArgs /** * @deprecated Use MeterDefaultArgs instead */ diff --git a/backend/node_modules/.prisma/client/index.js b/backend/node_modules/.prisma/client/index.js index b7415e60..10fc488d 100644 --- a/backend/node_modules/.prisma/client/index.js +++ b/backend/node_modules/.prisma/client/index.js @@ -106,6 +106,7 @@ exports.Prisma.UserScalarFieldEnum = { firstName: 'firstName', lastName: 'lastName', isActive: 'isActive', + tokenInvalidatedAt: 'tokenInvalidatedAt', customerId: 'customerId', createdAt: 'createdAt', updatedAt: 'updatedAt' @@ -228,6 +229,13 @@ exports.Prisma.EmailProviderConfigScalarFieldEnum = { passwordEncrypted: 'passwordEncrypted', domain: 'domain', defaultForwardEmail: 'defaultForwardEmail', + imapServer: 'imapServer', + imapPort: 'imapPort', + smtpServer: 'smtpServer', + smtpPort: 'smtpPort', + imapEncryption: 'imapEncryption', + smtpEncryption: 'smtpEncryption', + allowSelfSignedCerts: 'allowSelfSignedCerts', isActive: 'isActive', isDefault: 'isDefault', createdAt: 'createdAt', @@ -244,6 +252,36 @@ exports.Prisma.StressfreiEmailScalarFieldEnum = { isProvisioned: 'isProvisioned', provisionedAt: 'provisionedAt', provisionError: 'provisionError', + hasMailbox: 'hasMailbox', + emailPasswordEncrypted: 'emailPasswordEncrypted', + createdAt: 'createdAt', + updatedAt: 'updatedAt' +}; + +exports.Prisma.CachedEmailScalarFieldEnum = { + id: 'id', + stressfreiEmailId: 'stressfreiEmailId', + folder: 'folder', + messageId: 'messageId', + uid: 'uid', + subject: 'subject', + fromAddress: 'fromAddress', + fromName: 'fromName', + toAddresses: 'toAddresses', + ccAddresses: 'ccAddresses', + receivedAt: 'receivedAt', + textBody: 'textBody', + htmlBody: 'htmlBody', + hasAttachments: 'hasAttachments', + attachmentNames: 'attachmentNames', + contractId: 'contractId', + assignedAt: 'assignedAt', + assignedBy: 'assignedBy', + isAutoAssigned: 'isAutoAssigned', + isRead: 'isRead', + isStarred: 'isStarred', + isDeleted: 'isDeleted', + deletedAt: 'deletedAt', createdAt: 'createdAt', updatedAt: 'updatedAt' }; @@ -511,6 +549,17 @@ exports.EmailProviderType = exports.$Enums.EmailProviderType = { DIRECTADMIN: 'DIRECTADMIN' }; +exports.MailEncryption = exports.$Enums.MailEncryption = { + SSL: 'SSL', + STARTTLS: 'STARTTLS', + NONE: 'NONE' +}; + +exports.EmailFolder = exports.$Enums.EmailFolder = { + INBOX: 'INBOX', + SENT: 'SENT' +}; + exports.MeterType = exports.$Enums.MeterType = { ELECTRICITY: 'ELECTRICITY', GAS: 'GAS' @@ -561,6 +610,7 @@ exports.Prisma.ModelName = { IdentityDocument: 'IdentityDocument', EmailProviderConfig: 'EmailProviderConfig', StressfreiEmail: 'StressfreiEmail', + CachedEmail: 'CachedEmail', Meter: 'Meter', MeterReading: 'MeterReading', SalesPlatform: 'SalesPlatform', @@ -618,7 +668,6 @@ const config = { "db" ], "activeProvider": "mysql", - "postinstall": false, "inlineDatasources": { "db": { "url": { @@ -627,8 +676,8 @@ const config = { } } }, - "inlineSchema": "generator client {\n provider = \"prisma-client-js\"\n}\n\ndatasource db {\n provider = \"mysql\"\n url = env(\"DATABASE_URL\")\n}\n\n// ==================== APP SETTINGS ====================\n\nmodel AppSetting {\n id Int @id @default(autoincrement())\n key String @unique\n value String @db.Text\n createdAt DateTime @default(now())\n updatedAt DateTime @updatedAt\n}\n\n// ==================== USERS & AUTH ====================\n\nmodel User {\n id Int @id @default(autoincrement())\n email String @unique\n password String\n firstName String\n lastName String\n isActive Boolean @default(true)\n customerId Int? @unique\n customer Customer? @relation(fields: [customerId], references: [id])\n roles UserRole[]\n createdAt DateTime @default(now())\n updatedAt DateTime @updatedAt\n}\n\nmodel Role {\n id Int @id @default(autoincrement())\n name String @unique\n description String?\n permissions RolePermission[]\n users UserRole[]\n createdAt DateTime @default(now())\n updatedAt DateTime @updatedAt\n}\n\nmodel Permission {\n id Int @id @default(autoincrement())\n resource String\n action String\n roles RolePermission[]\n\n @@unique([resource, action])\n}\n\nmodel RolePermission {\n roleId Int\n permissionId Int\n role Role @relation(fields: [roleId], references: [id], onDelete: Cascade)\n permission Permission @relation(fields: [permissionId], references: [id], onDelete: Cascade)\n\n @@id([roleId, permissionId])\n}\n\nmodel UserRole {\n userId Int\n roleId Int\n user User @relation(fields: [userId], references: [id], onDelete: Cascade)\n role Role @relation(fields: [roleId], references: [id], onDelete: Cascade)\n\n @@id([userId, roleId])\n}\n\n// ==================== CUSTOMERS ====================\n\nenum CustomerType {\n PRIVATE\n BUSINESS\n}\n\nmodel Customer {\n id Int @id @default(autoincrement())\n customerNumber String @unique\n type CustomerType @default(PRIVATE)\n salutation String?\n firstName String\n lastName String\n companyName String?\n foundingDate DateTime? // Gründungsdatum (für Firmen)\n birthDate DateTime?\n birthPlace String?\n email String?\n phone String?\n mobile String?\n taxNumber String?\n businessRegistrationPath String? // PDF-Pfad zur Gewerbeanmeldung\n commercialRegisterPath String? // PDF-Pfad zum Handelsregisterauszug\n commercialRegisterNumber String? // Handelsregisternummer (Text)\n privacyPolicyPath String? // PDF-Pfad zur Datenschutzerklärung (für alle Kunden)\n notes String? @db.Text\n\n // ===== Portal-Zugangsdaten =====\n portalEnabled Boolean @default(false) // Portal aktiviert?\n portalEmail String? @unique // Portal-Login E-Mail\n portalPasswordHash String? // Gehashtes Passwort (für Login)\n portalPasswordEncrypted String? // Verschlüsseltes Passwort (für Anzeige)\n portalLastLogin DateTime? // Letzte Anmeldung\n\n user User?\n addresses Address[]\n bankCards BankCard[]\n identityDocuments IdentityDocument[]\n meters Meter[]\n stressfreiEmails StressfreiEmail[]\n contracts Contract[]\n\n // Vertreter-Beziehungen (Kunde kann für andere Kunden handeln)\n representingFor CustomerRepresentative[] @relation(\"RepresentativeCustomer\")\n representedBy CustomerRepresentative[] @relation(\"RepresentedCustomer\")\n\n createdAt DateTime @default(now())\n updatedAt DateTime @updatedAt\n}\n\n// ==================== CUSTOMER REPRESENTATIVES ====================\n// Vertretungsbeziehung: Ein Kunde kann die Verträge eines anderen Kunden einsehen\n// z.B. Sohn (representativeId) kann Verträge der Mutter (customerId) sehen\n\nmodel CustomerRepresentative {\n id Int @id @default(autoincrement())\n customerId Int // Der Kunde, dessen Verträge eingesehen werden (z.B. Mutter)\n customer Customer @relation(\"RepresentedCustomer\", fields: [customerId], references: [id], onDelete: Cascade)\n representativeId Int // Der Kunde, der einsehen darf (z.B. Sohn)\n representative Customer @relation(\"RepresentativeCustomer\", fields: [representativeId], references: [id], onDelete: Cascade)\n notes String? // Notizen zur Vertretung\n isActive Boolean @default(true)\n createdAt DateTime @default(now())\n updatedAt DateTime @updatedAt\n\n @@unique([customerId, representativeId]) // Keine doppelten Einträge\n}\n\n// ==================== ADDRESSES ====================\n\nenum AddressType {\n DELIVERY_RESIDENCE\n BILLING\n}\n\nmodel Address {\n id Int @id @default(autoincrement())\n customerId Int\n customer Customer @relation(fields: [customerId], references: [id], onDelete: Cascade)\n type AddressType @default(DELIVERY_RESIDENCE)\n street String\n houseNumber String\n postalCode String\n city String\n country String @default(\"Deutschland\")\n isDefault Boolean @default(false)\n contracts Contract[]\n createdAt DateTime @default(now())\n updatedAt DateTime @updatedAt\n}\n\n// ==================== BANK CARDS ====================\n\nmodel BankCard {\n id Int @id @default(autoincrement())\n customerId Int\n customer Customer @relation(fields: [customerId], references: [id], onDelete: Cascade)\n accountHolder String\n iban String\n bic String?\n bankName String?\n expiryDate DateTime?\n documentPath String? // Pfad zur hochgeladenen PDF\n isActive Boolean @default(true)\n contracts Contract[]\n createdAt DateTime @default(now())\n updatedAt DateTime @updatedAt\n}\n\n// ==================== IDENTITY DOCUMENTS ====================\n\nenum DocumentType {\n ID_CARD\n PASSPORT\n DRIVERS_LICENSE\n OTHER\n}\n\nmodel IdentityDocument {\n id Int @id @default(autoincrement())\n customerId Int\n customer Customer @relation(fields: [customerId], references: [id], onDelete: Cascade)\n type DocumentType @default(ID_CARD)\n documentNumber String\n issuingAuthority String?\n issueDate DateTime?\n expiryDate DateTime?\n documentPath String? // Pfad zur hochgeladenen PDF\n isActive Boolean @default(true)\n // Führerschein-spezifische Felder\n licenseClasses String? // z.B. \"B, BE, AM, L\" - kommasepariert\n licenseIssueDate DateTime? // Datum des Führerscheinerwerbs (Klasse B)\n contracts Contract[]\n createdAt DateTime @default(now())\n updatedAt DateTime @updatedAt\n}\n\n// ==================== EMAIL PROVIDER CONFIG (Plesk, cPanel etc.) ====================\n\nenum EmailProviderType {\n PLESK\n CPANEL\n DIRECTADMIN\n}\n\nmodel EmailProviderConfig {\n id Int @id @default(autoincrement())\n name String @unique // z.B. \"Plesk Hauptserver\"\n type EmailProviderType\n apiUrl String // API-URL (z.B. https://server.de:8443)\n apiKey String? // API-Key (verschlüsselt)\n username String? // Benutzername für API\n passwordEncrypted String? // Passwort (verschlüsselt)\n domain String // Domain für E-Mails (z.B. stressfrei-wechseln.de)\n defaultForwardEmail String? // Standard-Weiterleitungsadresse (unsere eigene)\n isActive Boolean @default(true)\n isDefault Boolean @default(false) // Standard-Provider\n createdAt DateTime @default(now())\n updatedAt DateTime @updatedAt\n}\n\n// ==================== STRESSFREI-WECHSELN EMAIL ADDRESSES ====================\n\nmodel StressfreiEmail {\n id Int @id @default(autoincrement())\n customerId Int\n customer Customer @relation(fields: [customerId], references: [id], onDelete: Cascade)\n email String // Die Weiterleitungs-E-Mail-Adresse\n platform String? // Für welche Plattform (z.B. \"Freenet\", \"Klarmobil\")\n notes String? @db.Text // Optionale Notizen\n isActive Boolean @default(true)\n isProvisioned Boolean @default(false) // Wurde bei Provider angelegt?\n provisionedAt DateTime? // Wann wurde provisioniert?\n provisionError String? @db.Text // Fehlermeldung falls Provisionierung fehlschlug\n contracts Contract[] // Verträge die diese E-Mail als Benutzername verwenden\n createdAt DateTime @default(now())\n updatedAt DateTime @updatedAt\n}\n\n// ==================== METERS (Energy) ====================\n\nenum MeterType {\n ELECTRICITY\n GAS\n}\n\nmodel Meter {\n id Int @id @default(autoincrement())\n customerId Int\n customer Customer @relation(fields: [customerId], references: [id], onDelete: Cascade)\n meterNumber String\n type MeterType\n location String?\n isActive Boolean @default(true)\n readings MeterReading[]\n energyDetails EnergyContractDetails[]\n createdAt DateTime @default(now())\n updatedAt DateTime @updatedAt\n}\n\nmodel MeterReading {\n id Int @id @default(autoincrement())\n meterId Int\n meter Meter @relation(fields: [meterId], references: [id], onDelete: Cascade)\n readingDate DateTime\n value Float\n unit String @default(\"kWh\")\n notes String?\n createdAt DateTime @default(now())\n}\n\n// ==================== SALES PLATFORMS ====================\n\nmodel SalesPlatform {\n id Int @id @default(autoincrement())\n name String @unique\n contactInfo String? @db.Text\n isActive Boolean @default(true)\n contracts Contract[]\n createdAt DateTime @default(now())\n updatedAt DateTime @updatedAt\n}\n\n// ==================== CANCELLATION PERIODS ====================\n\nmodel CancellationPeriod {\n id Int @id @default(autoincrement())\n code String @unique // z.B. \"14T\", \"1M\", \"3M\", \"12M\", \"1J\"\n description String // z.B. \"14 Tage\", \"1 Monat\", \"3 Monate\"\n isActive Boolean @default(true)\n contracts Contract[]\n createdAt DateTime @default(now())\n updatedAt DateTime @updatedAt\n}\n\n// ==================== CONTRACT DURATIONS ====================\n\nmodel ContractDuration {\n id Int @id @default(autoincrement())\n code String @unique // z.B. \"12M\", \"24M\", \"1J\", \"2J\"\n description String // z.B. \"12 Monate\", \"24 Monate\", \"1 Jahr\"\n isActive Boolean @default(true)\n contracts Contract[]\n createdAt DateTime @default(now())\n updatedAt DateTime @updatedAt\n}\n\n// ==================== PROVIDERS (Anbieter) ====================\n\nmodel Provider {\n id Int @id @default(autoincrement())\n name String @unique // Anbietername\n portalUrl String? // Kundenkontourl (Login-Seite)\n usernameFieldName String? // Benutzernamefeld (z.B. \"email\", \"username\")\n passwordFieldName String? // Kennwortfeld (z.B. \"password\", \"pwd\")\n isActive Boolean @default(true)\n tariffs Tariff[]\n contracts Contract[]\n createdAt DateTime @default(now())\n updatedAt DateTime @updatedAt\n}\n\n// ==================== TARIFFS (Tarife) ====================\n\nmodel Tariff {\n id Int @id @default(autoincrement())\n providerId Int\n provider Provider @relation(fields: [providerId], references: [id], onDelete: Cascade)\n name String // Tarifname\n isActive Boolean @default(true)\n contracts Contract[]\n createdAt DateTime @default(now())\n updatedAt DateTime @updatedAt\n\n @@unique([providerId, name]) // Eindeutiger Tarif pro Anbieter\n}\n\n// ==================== CONTRACT CATEGORIES ====================\n\nmodel ContractCategory {\n id Int @id @default(autoincrement())\n code String @unique // Technischer Code (z.B. ELECTRICITY, GAS)\n name String // Anzeigename (z.B. Strom, Gas)\n icon String? // Icon-Name für UI (z.B. \"Zap\", \"Flame\")\n color String? // Farbe für UI (z.B. \"#FFC107\")\n sortOrder Int @default(0)\n isActive Boolean @default(true)\n contracts Contract[]\n createdAt DateTime @default(now())\n updatedAt DateTime @updatedAt\n}\n\n// ==================== CONTRACTS ====================\n\n// Legacy Enum - wird durch ContractCategory ersetzt\nenum ContractType {\n ELECTRICITY\n GAS\n DSL\n CABLE\n FIBER\n MOBILE\n TV\n CAR_INSURANCE\n}\n\nenum ContractStatus {\n DRAFT\n PENDING\n ACTIVE\n CANCELLED\n EXPIRED\n DEACTIVATED\n}\n\nmodel Contract {\n id Int @id @default(autoincrement())\n contractNumber String @unique\n customerId Int\n customer Customer @relation(fields: [customerId], references: [id], onDelete: Cascade)\n type ContractType\n status ContractStatus @default(DRAFT)\n\n // Neue konfigurierbare Kategorie (ersetzt langfristig das type-Enum)\n contractCategoryId Int?\n contractCategory ContractCategory? @relation(fields: [contractCategoryId], references: [id])\n\n addressId Int?\n address Address? @relation(fields: [addressId], references: [id])\n\n bankCardId Int?\n bankCard BankCard? @relation(fields: [bankCardId], references: [id])\n\n identityDocumentId Int?\n identityDocument IdentityDocument? @relation(fields: [identityDocumentId], references: [id])\n\n salesPlatformId Int?\n salesPlatform SalesPlatform? @relation(fields: [salesPlatformId], references: [id])\n\n cancellationPeriodId Int?\n cancellationPeriod CancellationPeriod? @relation(fields: [cancellationPeriodId], references: [id])\n\n contractDurationId Int?\n contractDuration ContractDuration? @relation(fields: [contractDurationId], references: [id])\n\n previousContractId Int? @unique\n previousContract Contract? @relation(\"ContractHistory\", fields: [previousContractId], references: [id])\n followUpContract Contract? @relation(\"ContractHistory\")\n\n // Anbieter & Tarif (neue Verknüpfung)\n providerId Int?\n provider Provider? @relation(fields: [providerId], references: [id])\n tariffId Int?\n tariff Tariff? @relation(fields: [tariffId], references: [id])\n\n // Legacy-Felder (für Abwärtskompatibilität)\n providerName String?\n tariffName String?\n customerNumberAtProvider String?\n priceFirst12Months String? // Preis erste 12 Monate\n priceFrom13Months String? // Preis ab 13. Monat\n priceAfter24Months String? // Preis nach 24 Monaten\n\n startDate DateTime?\n endDate DateTime? // Wird aus startDate + contractDuration berechnet\n commission Float?\n\n // Kündigungsdokumente\n cancellationLetterPath String? // Kündigungsschreiben PDF\n cancellationConfirmationPath String? // Kündigungsbestätigung PDF\n cancellationLetterOptionsPath String? // Kündigungsschreiben Optionen PDF\n cancellationConfirmationOptionsPath String? // Kündigungsbestätigung Optionen PDF\n\n // Kündigungsdaten\n cancellationConfirmationDate DateTime? // Kündigungsbestätigungsdatum\n cancellationConfirmationOptionsDate DateTime? // Kündigungsbestätigungsoptionendatum\n wasSpecialCancellation Boolean @default(false) // Wurde sondergekündigt?\n\n portalUsername String?\n portalPasswordEncrypted String?\n\n // Stressfrei-Wechseln E-Mail als Benutzername (Alternative zu portalUsername)\n stressfreiEmailId Int?\n stressfreiEmail StressfreiEmail? @relation(fields: [stressfreiEmailId], references: [id])\n\n notes String? @db.Text\n\n energyDetails EnergyContractDetails?\n internetDetails InternetContractDetails?\n mobileDetails MobileContractDetails?\n tvDetails TvContractDetails?\n carInsuranceDetails CarInsuranceDetails?\n\n tasks ContractTask[]\n\n createdAt DateTime @default(now())\n updatedAt DateTime @updatedAt\n}\n\n// ==================== CONTRACT TASKS ====================\n\nenum ContractTaskStatus {\n OPEN\n COMPLETED\n}\n\nmodel ContractTask {\n id Int @id @default(autoincrement())\n contractId Int\n contract Contract @relation(fields: [contractId], references: [id], onDelete: Cascade)\n title String\n description String? @db.Text\n status ContractTaskStatus @default(OPEN)\n visibleInPortal Boolean @default(false)\n createdBy String? // Name des Erstellers\n completedAt DateTime?\n subtasks ContractTaskSubtask[]\n createdAt DateTime @default(now())\n updatedAt DateTime @updatedAt\n}\n\nmodel ContractTaskSubtask {\n id Int @id @default(autoincrement())\n taskId Int\n task ContractTask @relation(fields: [taskId], references: [id], onDelete: Cascade)\n title String\n status ContractTaskStatus @default(OPEN)\n createdBy String?\n completedAt DateTime?\n createdAt DateTime @default(now())\n updatedAt DateTime @updatedAt\n}\n\n// ==================== ENERGY CONTRACT DETAILS ====================\n\nmodel EnergyContractDetails {\n id Int @id @default(autoincrement())\n contractId Int @unique\n contract Contract @relation(fields: [contractId], references: [id], onDelete: Cascade)\n meterId Int?\n meter Meter? @relation(fields: [meterId], references: [id])\n annualConsumption Float?\n basePrice Float?\n unitPrice Float?\n bonus Float?\n previousProviderName String?\n previousCustomerNumber String?\n}\n\n// ==================== INTERNET CONTRACT DETAILS ====================\n\nmodel InternetContractDetails {\n id Int @id @default(autoincrement())\n contractId Int @unique\n contract Contract @relation(fields: [contractId], references: [id], onDelete: Cascade)\n downloadSpeed Int?\n uploadSpeed Int?\n routerModel String?\n routerSerialNumber String?\n installationDate DateTime?\n // Internet-Zugangsdaten\n internetUsername String?\n internetPasswordEncrypted String? // Verschlüsselt gespeichert\n // Glasfaser-spezifisch\n homeId String?\n // Vodafone DSL/Kabel spezifisch\n activationCode String?\n phoneNumbers PhoneNumber[]\n}\n\nmodel PhoneNumber {\n id Int @id @default(autoincrement())\n internetContractDetailsId Int\n internetDetails InternetContractDetails @relation(fields: [internetContractDetailsId], references: [id], onDelete: Cascade)\n phoneNumber String\n isMain Boolean @default(false)\n // SIP-Zugangsdaten\n sipUsername String?\n sipPasswordEncrypted String? // Verschlüsselt gespeichert\n sipServer String?\n}\n\n// ==================== MOBILE CONTRACT DETAILS ====================\n\nmodel MobileContractDetails {\n id Int @id @default(autoincrement())\n contractId Int @unique\n contract Contract @relation(fields: [contractId], references: [id], onDelete: Cascade)\n requiresMultisim Boolean @default(false) // Multisim erforderlich?\n dataVolume Float?\n includedMinutes Int?\n includedSMS Int?\n deviceModel String?\n deviceImei String?\n simCards SimCard[]\n // Legacy-Felder (für Abwärtskompatibilität, werden durch simCards ersetzt)\n phoneNumber String?\n simCardNumber String?\n}\n\nmodel SimCard {\n id Int @id @default(autoincrement())\n mobileDetailsId Int\n mobileDetails MobileContractDetails @relation(fields: [mobileDetailsId], references: [id], onDelete: Cascade)\n phoneNumber String? // Rufnummer\n simCardNumber String? // SIM-Kartennummer\n pin String? // PIN (verschlüsselt gespeichert)\n puk String? // PUK (verschlüsselt gespeichert)\n isMultisim Boolean @default(false) // Ist dies eine Multisim-Karte?\n isMain Boolean @default(false) // Ist dies die Hauptkarte?\n createdAt DateTime @default(now())\n updatedAt DateTime @updatedAt\n}\n\n// ==================== TV CONTRACT DETAILS ====================\n\nmodel TvContractDetails {\n id Int @id @default(autoincrement())\n contractId Int @unique\n contract Contract @relation(fields: [contractId], references: [id], onDelete: Cascade)\n receiverModel String?\n smartcardNumber String?\n package String?\n}\n\n// ==================== CAR INSURANCE DETAILS ====================\n\nenum InsuranceType {\n LIABILITY\n PARTIAL\n FULL\n}\n\nmodel CarInsuranceDetails {\n id Int @id @default(autoincrement())\n contractId Int @unique\n contract Contract @relation(fields: [contractId], references: [id], onDelete: Cascade)\n licensePlate String?\n hsn String?\n tsn String?\n vin String?\n vehicleType String?\n firstRegistration DateTime?\n noClaimsClass String?\n insuranceType InsuranceType @default(LIABILITY)\n deductiblePartial Float?\n deductibleFull Float?\n policyNumber String?\n previousInsurer String?\n}\n", - "inlineSchemaHash": "36ecbca17fa945f160ba1bb4a7cfa1b4971e63c59c4e05b0dcc483003048b598", + "inlineSchema": "generator client {\n provider = \"prisma-client-js\"\n}\n\ndatasource db {\n provider = \"mysql\"\n url = env(\"DATABASE_URL\")\n}\n\n// ==================== APP SETTINGS ====================\n\nmodel AppSetting {\n id Int @id @default(autoincrement())\n key String @unique\n value String @db.Text\n createdAt DateTime @default(now())\n updatedAt DateTime @updatedAt\n}\n\n// ==================== USERS & AUTH ====================\n\nmodel User {\n id Int @id @default(autoincrement())\n email String @unique\n password String\n firstName String\n lastName String\n isActive Boolean @default(true)\n tokenInvalidatedAt DateTime? // Zeitpunkt ab dem alle Tokens ungültig sind (für Zwangslogout bei Rechteänderung)\n customerId Int? @unique\n customer Customer? @relation(fields: [customerId], references: [id])\n roles UserRole[]\n createdAt DateTime @default(now())\n updatedAt DateTime @updatedAt\n}\n\nmodel Role {\n id Int @id @default(autoincrement())\n name String @unique\n description String?\n permissions RolePermission[]\n users UserRole[]\n createdAt DateTime @default(now())\n updatedAt DateTime @updatedAt\n}\n\nmodel Permission {\n id Int @id @default(autoincrement())\n resource String\n action String\n roles RolePermission[]\n\n @@unique([resource, action])\n}\n\nmodel RolePermission {\n roleId Int\n permissionId Int\n role Role @relation(fields: [roleId], references: [id], onDelete: Cascade)\n permission Permission @relation(fields: [permissionId], references: [id], onDelete: Cascade)\n\n @@id([roleId, permissionId])\n}\n\nmodel UserRole {\n userId Int\n roleId Int\n user User @relation(fields: [userId], references: [id], onDelete: Cascade)\n role Role @relation(fields: [roleId], references: [id], onDelete: Cascade)\n\n @@id([userId, roleId])\n}\n\n// ==================== CUSTOMERS ====================\n\nenum CustomerType {\n PRIVATE\n BUSINESS\n}\n\nmodel Customer {\n id Int @id @default(autoincrement())\n customerNumber String @unique\n type CustomerType @default(PRIVATE)\n salutation String?\n firstName String\n lastName String\n companyName String?\n foundingDate DateTime? // Gründungsdatum (für Firmen)\n birthDate DateTime?\n birthPlace String?\n email String?\n phone String?\n mobile String?\n taxNumber String?\n businessRegistrationPath String? // PDF-Pfad zur Gewerbeanmeldung\n commercialRegisterPath String? // PDF-Pfad zum Handelsregisterauszug\n commercialRegisterNumber String? // Handelsregisternummer (Text)\n privacyPolicyPath String? // PDF-Pfad zur Datenschutzerklärung (für alle Kunden)\n notes String? @db.Text\n\n // ===== Portal-Zugangsdaten =====\n portalEnabled Boolean @default(false) // Portal aktiviert?\n portalEmail String? @unique // Portal-Login E-Mail\n portalPasswordHash String? // Gehashtes Passwort (für Login)\n portalPasswordEncrypted String? // Verschlüsseltes Passwort (für Anzeige)\n portalLastLogin DateTime? // Letzte Anmeldung\n\n user User?\n addresses Address[]\n bankCards BankCard[]\n identityDocuments IdentityDocument[]\n meters Meter[]\n stressfreiEmails StressfreiEmail[]\n contracts Contract[]\n\n // Vertreter-Beziehungen (Kunde kann für andere Kunden handeln)\n representingFor CustomerRepresentative[] @relation(\"RepresentativeCustomer\")\n representedBy CustomerRepresentative[] @relation(\"RepresentedCustomer\")\n\n createdAt DateTime @default(now())\n updatedAt DateTime @updatedAt\n}\n\n// ==================== CUSTOMER REPRESENTATIVES ====================\n// Vertretungsbeziehung: Ein Kunde kann die Verträge eines anderen Kunden einsehen\n// z.B. Sohn (representativeId) kann Verträge der Mutter (customerId) sehen\n\nmodel CustomerRepresentative {\n id Int @id @default(autoincrement())\n customerId Int // Der Kunde, dessen Verträge eingesehen werden (z.B. Mutter)\n customer Customer @relation(\"RepresentedCustomer\", fields: [customerId], references: [id], onDelete: Cascade)\n representativeId Int // Der Kunde, der einsehen darf (z.B. Sohn)\n representative Customer @relation(\"RepresentativeCustomer\", fields: [representativeId], references: [id], onDelete: Cascade)\n notes String? // Notizen zur Vertretung\n isActive Boolean @default(true)\n createdAt DateTime @default(now())\n updatedAt DateTime @updatedAt\n\n @@unique([customerId, representativeId]) // Keine doppelten Einträge\n}\n\n// ==================== ADDRESSES ====================\n\nenum AddressType {\n DELIVERY_RESIDENCE\n BILLING\n}\n\nmodel Address {\n id Int @id @default(autoincrement())\n customerId Int\n customer Customer @relation(fields: [customerId], references: [id], onDelete: Cascade)\n type AddressType @default(DELIVERY_RESIDENCE)\n street String\n houseNumber String\n postalCode String\n city String\n country String @default(\"Deutschland\")\n isDefault Boolean @default(false)\n contracts Contract[]\n createdAt DateTime @default(now())\n updatedAt DateTime @updatedAt\n}\n\n// ==================== BANK CARDS ====================\n\nmodel BankCard {\n id Int @id @default(autoincrement())\n customerId Int\n customer Customer @relation(fields: [customerId], references: [id], onDelete: Cascade)\n accountHolder String\n iban String\n bic String?\n bankName String?\n expiryDate DateTime?\n documentPath String? // Pfad zur hochgeladenen PDF\n isActive Boolean @default(true)\n contracts Contract[]\n createdAt DateTime @default(now())\n updatedAt DateTime @updatedAt\n}\n\n// ==================== IDENTITY DOCUMENTS ====================\n\nenum DocumentType {\n ID_CARD\n PASSPORT\n DRIVERS_LICENSE\n OTHER\n}\n\nmodel IdentityDocument {\n id Int @id @default(autoincrement())\n customerId Int\n customer Customer @relation(fields: [customerId], references: [id], onDelete: Cascade)\n type DocumentType @default(ID_CARD)\n documentNumber String\n issuingAuthority String?\n issueDate DateTime?\n expiryDate DateTime?\n documentPath String? // Pfad zur hochgeladenen PDF\n isActive Boolean @default(true)\n // Führerschein-spezifische Felder\n licenseClasses String? // z.B. \"B, BE, AM, L\" - kommasepariert\n licenseIssueDate DateTime? // Datum des Führerscheinerwerbs (Klasse B)\n contracts Contract[]\n createdAt DateTime @default(now())\n updatedAt DateTime @updatedAt\n}\n\n// ==================== EMAIL PROVIDER CONFIG (Plesk, cPanel etc.) ====================\n\nenum EmailProviderType {\n PLESK\n CPANEL\n DIRECTADMIN\n}\n\n// Verschlüsselungstyp für E-Mail-Verbindungen\nenum MailEncryption {\n SSL // Implicit SSL/TLS (Ports 465/993) - Verschlüsselung von Anfang an\n STARTTLS // STARTTLS (Ports 587/143) - Startet unverschlüsselt, dann Upgrade\n NONE // Keine Verschlüsselung (Ports 25/143)\n}\n\nmodel EmailProviderConfig {\n id Int @id @default(autoincrement())\n name String @unique // z.B. \"Plesk Hauptserver\"\n type EmailProviderType\n apiUrl String // API-URL (z.B. https://server.de:8443)\n apiKey String? // API-Key (verschlüsselt)\n username String? // Benutzername für API\n passwordEncrypted String? // Passwort (verschlüsselt)\n domain String // Domain für E-Mails (z.B. stressfrei-wechseln.de)\n defaultForwardEmail String? // Standard-Weiterleitungsadresse (unsere eigene)\n\n // IMAP/SMTP-Server für E-Mail-Client (optional, default: mail.{domain})\n imapServer String? // z.B. \"mail.stressfrei-wechseln.de\"\n imapPort Int? @default(993)\n smtpServer String?\n smtpPort Int? @default(465)\n\n // Verschlüsselungs-Einstellungen\n imapEncryption MailEncryption @default(SSL) // SSL, STARTTLS oder NONE\n smtpEncryption MailEncryption @default(SSL) // SSL, STARTTLS oder NONE\n allowSelfSignedCerts Boolean @default(false) // Selbstsignierte Zertifikate erlauben\n\n isActive Boolean @default(true)\n isDefault Boolean @default(false) // Standard-Provider\n createdAt DateTime @default(now())\n updatedAt DateTime @updatedAt\n}\n\n// ==================== STRESSFREI-WECHSELN EMAIL ADDRESSES ====================\n\nmodel StressfreiEmail {\n id Int @id @default(autoincrement())\n customerId Int\n customer Customer @relation(fields: [customerId], references: [id], onDelete: Cascade)\n email String // Die Weiterleitungs-E-Mail-Adresse\n platform String? // Für welche Plattform (z.B. \"Freenet\", \"Klarmobil\")\n notes String? @db.Text // Optionale Notizen\n isActive Boolean @default(true)\n isProvisioned Boolean @default(false) // Wurde bei Provider angelegt?\n provisionedAt DateTime? // Wann wurde provisioniert?\n provisionError String? @db.Text // Fehlermeldung falls Provisionierung fehlschlug\n\n // Mailbox-Zugangsdaten (für IMAP/SMTP-Zugang)\n hasMailbox Boolean @default(false) // Hat echte Mailbox (nicht nur Weiterleitung)?\n emailPasswordEncrypted String? // Verschlüsseltes Mailbox-Passwort (AES-256-GCM)\n\n contracts Contract[] // Verträge die diese E-Mail als Benutzername verwenden\n cachedEmails CachedEmail[] // Gecachte E-Mails aus dieser Mailbox\n createdAt DateTime @default(now())\n updatedAt DateTime @updatedAt\n}\n\n// ==================== CACHED EMAILS (E-Mail-Client) ====================\n\nenum EmailFolder {\n INBOX\n SENT\n}\n\nmodel CachedEmail {\n id Int @id @default(autoincrement())\n stressfreiEmailId Int\n stressfreiEmail StressfreiEmail @relation(fields: [stressfreiEmailId], references: [id], onDelete: Cascade)\n\n // Ordner (Posteingang oder Gesendet)\n folder EmailFolder @default(INBOX)\n\n // IMAP-Identifikation\n messageId String // RFC 5322 Message-ID\n uid Int // IMAP UID (für Synchronisierung, bei SENT = 0)\n\n // E-Mail-Metadaten\n subject String?\n fromAddress String\n fromName String?\n toAddresses String @db.Text // JSON Array\n ccAddresses String? @db.Text // JSON Array\n receivedAt DateTime\n\n // Inhalt\n textBody String? @db.LongText\n htmlBody String? @db.LongText\n hasAttachments Boolean @default(false)\n attachmentNames String? @db.Text // JSON Array\n\n // Vertragszuordnung\n contractId Int?\n contract Contract? @relation(fields: [contractId], references: [id], onDelete: SetNull)\n assignedAt DateTime?\n assignedBy Int? // User ID der die Zuordnung gemacht hat\n isAutoAssigned Boolean @default(false) // true = automatisch beim Senden aus Vertrag\n\n // Flags\n isRead Boolean @default(false)\n isStarred Boolean @default(false)\n\n // Papierkorb\n isDeleted Boolean @default(false) // Im Papierkorb?\n deletedAt DateTime? // Wann gelöscht?\n\n createdAt DateTime @default(now())\n updatedAt DateTime @updatedAt\n\n @@unique([stressfreiEmailId, messageId, folder]) // Folder hinzugefügt: gleiche MessageID kann in INBOX und SENT existieren\n @@index([contractId])\n @@index([stressfreiEmailId, folder, receivedAt])\n @@index([stressfreiEmailId, isDeleted]) // Für Papierkorb-Abfragen\n}\n\n// ==================== METERS (Energy) ====================\n\nenum MeterType {\n ELECTRICITY\n GAS\n}\n\nmodel Meter {\n id Int @id @default(autoincrement())\n customerId Int\n customer Customer @relation(fields: [customerId], references: [id], onDelete: Cascade)\n meterNumber String\n type MeterType\n location String?\n isActive Boolean @default(true)\n readings MeterReading[]\n energyDetails EnergyContractDetails[]\n createdAt DateTime @default(now())\n updatedAt DateTime @updatedAt\n}\n\nmodel MeterReading {\n id Int @id @default(autoincrement())\n meterId Int\n meter Meter @relation(fields: [meterId], references: [id], onDelete: Cascade)\n readingDate DateTime\n value Float\n unit String @default(\"kWh\")\n notes String?\n createdAt DateTime @default(now())\n}\n\n// ==================== SALES PLATFORMS ====================\n\nmodel SalesPlatform {\n id Int @id @default(autoincrement())\n name String @unique\n contactInfo String? @db.Text\n isActive Boolean @default(true)\n contracts Contract[]\n createdAt DateTime @default(now())\n updatedAt DateTime @updatedAt\n}\n\n// ==================== CANCELLATION PERIODS ====================\n\nmodel CancellationPeriod {\n id Int @id @default(autoincrement())\n code String @unique // z.B. \"14T\", \"1M\", \"3M\", \"12M\", \"1J\"\n description String // z.B. \"14 Tage\", \"1 Monat\", \"3 Monate\"\n isActive Boolean @default(true)\n contracts Contract[]\n createdAt DateTime @default(now())\n updatedAt DateTime @updatedAt\n}\n\n// ==================== CONTRACT DURATIONS ====================\n\nmodel ContractDuration {\n id Int @id @default(autoincrement())\n code String @unique // z.B. \"12M\", \"24M\", \"1J\", \"2J\"\n description String // z.B. \"12 Monate\", \"24 Monate\", \"1 Jahr\"\n isActive Boolean @default(true)\n contracts Contract[]\n createdAt DateTime @default(now())\n updatedAt DateTime @updatedAt\n}\n\n// ==================== PROVIDERS (Anbieter) ====================\n\nmodel Provider {\n id Int @id @default(autoincrement())\n name String @unique // Anbietername\n portalUrl String? // Kundenkontourl (Login-Seite)\n usernameFieldName String? // Benutzernamefeld (z.B. \"email\", \"username\")\n passwordFieldName String? // Kennwortfeld (z.B. \"password\", \"pwd\")\n isActive Boolean @default(true)\n tariffs Tariff[]\n contracts Contract[]\n createdAt DateTime @default(now())\n updatedAt DateTime @updatedAt\n}\n\n// ==================== TARIFFS (Tarife) ====================\n\nmodel Tariff {\n id Int @id @default(autoincrement())\n providerId Int\n provider Provider @relation(fields: [providerId], references: [id], onDelete: Cascade)\n name String // Tarifname\n isActive Boolean @default(true)\n contracts Contract[]\n createdAt DateTime @default(now())\n updatedAt DateTime @updatedAt\n\n @@unique([providerId, name]) // Eindeutiger Tarif pro Anbieter\n}\n\n// ==================== CONTRACT CATEGORIES ====================\n\nmodel ContractCategory {\n id Int @id @default(autoincrement())\n code String @unique // Technischer Code (z.B. ELECTRICITY, GAS)\n name String // Anzeigename (z.B. Strom, Gas)\n icon String? // Icon-Name für UI (z.B. \"Zap\", \"Flame\")\n color String? // Farbe für UI (z.B. \"#FFC107\")\n sortOrder Int @default(0)\n isActive Boolean @default(true)\n contracts Contract[]\n createdAt DateTime @default(now())\n updatedAt DateTime @updatedAt\n}\n\n// ==================== CONTRACTS ====================\n\n// Legacy Enum - wird durch ContractCategory ersetzt\nenum ContractType {\n ELECTRICITY\n GAS\n DSL\n CABLE\n FIBER\n MOBILE\n TV\n CAR_INSURANCE\n}\n\nenum ContractStatus {\n DRAFT\n PENDING\n ACTIVE\n CANCELLED\n EXPIRED\n DEACTIVATED\n}\n\nmodel Contract {\n id Int @id @default(autoincrement())\n contractNumber String @unique\n customerId Int\n customer Customer @relation(fields: [customerId], references: [id], onDelete: Cascade)\n type ContractType\n status ContractStatus @default(DRAFT)\n\n // Neue konfigurierbare Kategorie (ersetzt langfristig das type-Enum)\n contractCategoryId Int?\n contractCategory ContractCategory? @relation(fields: [contractCategoryId], references: [id])\n\n addressId Int?\n address Address? @relation(fields: [addressId], references: [id])\n\n bankCardId Int?\n bankCard BankCard? @relation(fields: [bankCardId], references: [id])\n\n identityDocumentId Int?\n identityDocument IdentityDocument? @relation(fields: [identityDocumentId], references: [id])\n\n salesPlatformId Int?\n salesPlatform SalesPlatform? @relation(fields: [salesPlatformId], references: [id])\n\n cancellationPeriodId Int?\n cancellationPeriod CancellationPeriod? @relation(fields: [cancellationPeriodId], references: [id])\n\n contractDurationId Int?\n contractDuration ContractDuration? @relation(fields: [contractDurationId], references: [id])\n\n previousContractId Int? @unique\n previousContract Contract? @relation(\"ContractHistory\", fields: [previousContractId], references: [id])\n followUpContract Contract? @relation(\"ContractHistory\")\n\n // Anbieter & Tarif (neue Verknüpfung)\n providerId Int?\n provider Provider? @relation(fields: [providerId], references: [id])\n tariffId Int?\n tariff Tariff? @relation(fields: [tariffId], references: [id])\n\n // Legacy-Felder (für Abwärtskompatibilität)\n providerName String?\n tariffName String?\n customerNumberAtProvider String?\n priceFirst12Months String? // Preis erste 12 Monate\n priceFrom13Months String? // Preis ab 13. Monat\n priceAfter24Months String? // Preis nach 24 Monaten\n\n startDate DateTime?\n endDate DateTime? // Wird aus startDate + contractDuration berechnet\n commission Float?\n\n // Kündigungsdokumente\n cancellationLetterPath String? // Kündigungsschreiben PDF\n cancellationConfirmationPath String? // Kündigungsbestätigung PDF\n cancellationLetterOptionsPath String? // Kündigungsschreiben Optionen PDF\n cancellationConfirmationOptionsPath String? // Kündigungsbestätigung Optionen PDF\n\n // Kündigungsdaten\n cancellationConfirmationDate DateTime? // Kündigungsbestätigungsdatum\n cancellationConfirmationOptionsDate DateTime? // Kündigungsbestätigungsoptionendatum\n wasSpecialCancellation Boolean @default(false) // Wurde sondergekündigt?\n\n portalUsername String?\n portalPasswordEncrypted String?\n\n // Stressfrei-Wechseln E-Mail als Benutzername (Alternative zu portalUsername)\n stressfreiEmailId Int?\n stressfreiEmail StressfreiEmail? @relation(fields: [stressfreiEmailId], references: [id])\n\n notes String? @db.Text\n\n energyDetails EnergyContractDetails?\n internetDetails InternetContractDetails?\n mobileDetails MobileContractDetails?\n tvDetails TvContractDetails?\n carInsuranceDetails CarInsuranceDetails?\n\n tasks ContractTask[]\n assignedEmails CachedEmail[] // Zugeordnete E-Mails aus dem E-Mail-Client\n\n createdAt DateTime @default(now())\n updatedAt DateTime @updatedAt\n}\n\n// ==================== CONTRACT TASKS ====================\n\nenum ContractTaskStatus {\n OPEN\n COMPLETED\n}\n\nmodel ContractTask {\n id Int @id @default(autoincrement())\n contractId Int\n contract Contract @relation(fields: [contractId], references: [id], onDelete: Cascade)\n title String\n description String? @db.Text\n status ContractTaskStatus @default(OPEN)\n visibleInPortal Boolean @default(false)\n createdBy String? // Name des Erstellers\n completedAt DateTime?\n subtasks ContractTaskSubtask[]\n createdAt DateTime @default(now())\n updatedAt DateTime @updatedAt\n}\n\nmodel ContractTaskSubtask {\n id Int @id @default(autoincrement())\n taskId Int\n task ContractTask @relation(fields: [taskId], references: [id], onDelete: Cascade)\n title String\n status ContractTaskStatus @default(OPEN)\n createdBy String?\n completedAt DateTime?\n createdAt DateTime @default(now())\n updatedAt DateTime @updatedAt\n}\n\n// ==================== ENERGY CONTRACT DETAILS ====================\n\nmodel EnergyContractDetails {\n id Int @id @default(autoincrement())\n contractId Int @unique\n contract Contract @relation(fields: [contractId], references: [id], onDelete: Cascade)\n meterId Int?\n meter Meter? @relation(fields: [meterId], references: [id])\n annualConsumption Float?\n basePrice Float?\n unitPrice Float?\n bonus Float?\n previousProviderName String?\n previousCustomerNumber String?\n}\n\n// ==================== INTERNET CONTRACT DETAILS ====================\n\nmodel InternetContractDetails {\n id Int @id @default(autoincrement())\n contractId Int @unique\n contract Contract @relation(fields: [contractId], references: [id], onDelete: Cascade)\n downloadSpeed Int?\n uploadSpeed Int?\n routerModel String?\n routerSerialNumber String?\n installationDate DateTime?\n // Internet-Zugangsdaten\n internetUsername String?\n internetPasswordEncrypted String? // Verschlüsselt gespeichert\n // Glasfaser-spezifisch\n homeId String?\n // Vodafone DSL/Kabel spezifisch\n activationCode String?\n phoneNumbers PhoneNumber[]\n}\n\nmodel PhoneNumber {\n id Int @id @default(autoincrement())\n internetContractDetailsId Int\n internetDetails InternetContractDetails @relation(fields: [internetContractDetailsId], references: [id], onDelete: Cascade)\n phoneNumber String\n isMain Boolean @default(false)\n // SIP-Zugangsdaten\n sipUsername String?\n sipPasswordEncrypted String? // Verschlüsselt gespeichert\n sipServer String?\n}\n\n// ==================== MOBILE CONTRACT DETAILS ====================\n\nmodel MobileContractDetails {\n id Int @id @default(autoincrement())\n contractId Int @unique\n contract Contract @relation(fields: [contractId], references: [id], onDelete: Cascade)\n requiresMultisim Boolean @default(false) // Multisim erforderlich?\n dataVolume Float?\n includedMinutes Int?\n includedSMS Int?\n deviceModel String?\n deviceImei String?\n simCards SimCard[]\n // Legacy-Felder (für Abwärtskompatibilität, werden durch simCards ersetzt)\n phoneNumber String?\n simCardNumber String?\n}\n\nmodel SimCard {\n id Int @id @default(autoincrement())\n mobileDetailsId Int\n mobileDetails MobileContractDetails @relation(fields: [mobileDetailsId], references: [id], onDelete: Cascade)\n phoneNumber String? // Rufnummer\n simCardNumber String? // SIM-Kartennummer\n pin String? // PIN (verschlüsselt gespeichert)\n puk String? // PUK (verschlüsselt gespeichert)\n isMultisim Boolean @default(false) // Ist dies eine Multisim-Karte?\n isMain Boolean @default(false) // Ist dies die Hauptkarte?\n createdAt DateTime @default(now())\n updatedAt DateTime @updatedAt\n}\n\n// ==================== TV CONTRACT DETAILS ====================\n\nmodel TvContractDetails {\n id Int @id @default(autoincrement())\n contractId Int @unique\n contract Contract @relation(fields: [contractId], references: [id], onDelete: Cascade)\n receiverModel String?\n smartcardNumber String?\n package String?\n}\n\n// ==================== CAR INSURANCE DETAILS ====================\n\nenum InsuranceType {\n LIABILITY\n PARTIAL\n FULL\n}\n\nmodel CarInsuranceDetails {\n id Int @id @default(autoincrement())\n contractId Int @unique\n contract Contract @relation(fields: [contractId], references: [id], onDelete: Cascade)\n licensePlate String?\n hsn String?\n tsn String?\n vin String?\n vehicleType String?\n firstRegistration DateTime?\n noClaimsClass String?\n insuranceType InsuranceType @default(LIABILITY)\n deductiblePartial Float?\n deductibleFull Float?\n policyNumber String?\n previousInsurer String?\n}\n", + "inlineSchemaHash": "0275307bf5bad35d995156e9cf00dc7906b05135b28bd545b6e7e6322aaa01ab", "copyEngine": true } @@ -649,7 +698,7 @@ if (!fs.existsSync(path.join(__dirname, 'schema.prisma'))) { config.isBundled = true } -config.runtimeDataModel = JSON.parse("{\"models\":{\"AppSetting\":{\"dbName\":null,\"fields\":[{\"name\":\"id\",\"kind\":\"scalar\",\"isList\":false,\"isRequired\":true,\"isUnique\":false,\"isId\":true,\"isReadOnly\":false,\"hasDefaultValue\":true,\"type\":\"Int\",\"default\":{\"name\":\"autoincrement\",\"args\":[]},\"isGenerated\":false,\"isUpdatedAt\":false},{\"name\":\"key\",\"kind\":\"scalar\",\"isList\":false,\"isRequired\":true,\"isUnique\":true,\"isId\":false,\"isReadOnly\":false,\"hasDefaultValue\":false,\"type\":\"String\",\"isGenerated\":false,\"isUpdatedAt\":false},{\"name\":\"value\",\"kind\":\"scalar\",\"isList\":false,\"isRequired\":true,\"isUnique\":false,\"isId\":false,\"isReadOnly\":false,\"hasDefaultValue\":false,\"type\":\"String\",\"isGenerated\":false,\"isUpdatedAt\":false},{\"name\":\"createdAt\",\"kind\":\"scalar\",\"isList\":false,\"isRequired\":true,\"isUnique\":false,\"isId\":false,\"isReadOnly\":false,\"hasDefaultValue\":true,\"type\":\"DateTime\",\"default\":{\"name\":\"now\",\"args\":[]},\"isGenerated\":false,\"isUpdatedAt\":false},{\"name\":\"updatedAt\",\"kind\":\"scalar\",\"isList\":false,\"isRequired\":true,\"isUnique\":false,\"isId\":false,\"isReadOnly\":false,\"hasDefaultValue\":false,\"type\":\"DateTime\",\"isGenerated\":false,\"isUpdatedAt\":true}],\"primaryKey\":null,\"uniqueFields\":[],\"uniqueIndexes\":[],\"isGenerated\":false},\"User\":{\"dbName\":null,\"fields\":[{\"name\":\"id\",\"kind\":\"scalar\",\"isList\":false,\"isRequired\":true,\"isUnique\":false,\"isId\":true,\"isReadOnly\":false,\"hasDefaultValue\":true,\"type\":\"Int\",\"default\":{\"name\":\"autoincrement\",\"args\":[]},\"isGenerated\":false,\"isUpdatedAt\":false},{\"name\":\"email\",\"kind\":\"scalar\",\"isList\":false,\"isRequired\":true,\"isUnique\":true,\"isId\":false,\"isReadOnly\":false,\"hasDefaultValue\":false,\"type\":\"String\",\"isGenerated\":false,\"isUpdatedAt\":false},{\"name\":\"password\",\"kind\":\"scalar\",\"isList\":false,\"isRequired\":true,\"isUnique\":false,\"isId\":false,\"isReadOnly\":false,\"hasDefaultValue\":false,\"type\":\"String\",\"isGenerated\":false,\"isUpdatedAt\":false},{\"name\":\"firstName\",\"kind\":\"scalar\",\"isList\":false,\"isRequired\":true,\"isUnique\":false,\"isId\":false,\"isReadOnly\":false,\"hasDefaultValue\":false,\"type\":\"String\",\"isGenerated\":false,\"isUpdatedAt\":false},{\"name\":\"lastName\",\"kind\":\"scalar\",\"isList\":false,\"isRequired\":true,\"isUnique\":false,\"isId\":false,\"isReadOnly\":false,\"hasDefaultValue\":false,\"type\":\"String\",\"isGenerated\":false,\"isUpdatedAt\":false},{\"name\":\"isActive\",\"kind\":\"scalar\",\"isList\":false,\"isRequired\":true,\"isUnique\":false,\"isId\":false,\"isReadOnly\":false,\"hasDefaultValue\":true,\"type\":\"Boolean\",\"default\":true,\"isGenerated\":false,\"isUpdatedAt\":false},{\"name\":\"customerId\",\"kind\":\"scalar\",\"isList\":false,\"isRequired\":false,\"isUnique\":true,\"isId\":false,\"isReadOnly\":true,\"hasDefaultValue\":false,\"type\":\"Int\",\"isGenerated\":false,\"isUpdatedAt\":false},{\"name\":\"customer\",\"kind\":\"object\",\"isList\":false,\"isRequired\":false,\"isUnique\":false,\"isId\":false,\"isReadOnly\":false,\"hasDefaultValue\":false,\"type\":\"Customer\",\"relationName\":\"CustomerToUser\",\"relationFromFields\":[\"customerId\"],\"relationToFields\":[\"id\"],\"isGenerated\":false,\"isUpdatedAt\":false},{\"name\":\"roles\",\"kind\":\"object\",\"isList\":true,\"isRequired\":true,\"isUnique\":false,\"isId\":false,\"isReadOnly\":false,\"hasDefaultValue\":false,\"type\":\"UserRole\",\"relationName\":\"UserToUserRole\",\"relationFromFields\":[],\"relationToFields\":[],\"isGenerated\":false,\"isUpdatedAt\":false},{\"name\":\"createdAt\",\"kind\":\"scalar\",\"isList\":false,\"isRequired\":true,\"isUnique\":false,\"isId\":false,\"isReadOnly\":false,\"hasDefaultValue\":true,\"type\":\"DateTime\",\"default\":{\"name\":\"now\",\"args\":[]},\"isGenerated\":false,\"isUpdatedAt\":false},{\"name\":\"updatedAt\",\"kind\":\"scalar\",\"isList\":false,\"isRequired\":true,\"isUnique\":false,\"isId\":false,\"isReadOnly\":false,\"hasDefaultValue\":false,\"type\":\"DateTime\",\"isGenerated\":false,\"isUpdatedAt\":true}],\"primaryKey\":null,\"uniqueFields\":[],\"uniqueIndexes\":[],\"isGenerated\":false},\"Role\":{\"dbName\":null,\"fields\":[{\"name\":\"id\",\"kind\":\"scalar\",\"isList\":false,\"isRequired\":true,\"isUnique\":false,\"isId\":true,\"isReadOnly\":false,\"hasDefaultValue\":true,\"type\":\"Int\",\"default\":{\"name\":\"autoincrement\",\"args\":[]},\"isGenerated\":false,\"isUpdatedAt\":false},{\"name\":\"name\",\"kind\":\"scalar\",\"isList\":false,\"isRequired\":true,\"isUnique\":true,\"isId\":false,\"isReadOnly\":false,\"hasDefaultValue\":false,\"type\":\"String\",\"isGenerated\":false,\"isUpdatedAt\":false},{\"name\":\"description\",\"kind\":\"scalar\",\"isList\":false,\"isRequired\":false,\"isUnique\":false,\"isId\":false,\"isReadOnly\":false,\"hasDefaultValue\":false,\"type\":\"String\",\"isGenerated\":false,\"isUpdatedAt\":false},{\"name\":\"permissions\",\"kind\":\"object\",\"isList\":true,\"isRequired\":true,\"isUnique\":false,\"isId\":false,\"isReadOnly\":false,\"hasDefaultValue\":false,\"type\":\"RolePermission\",\"relationName\":\"RoleToRolePermission\",\"relationFromFields\":[],\"relationToFields\":[],\"isGenerated\":false,\"isUpdatedAt\":false},{\"name\":\"users\",\"kind\":\"object\",\"isList\":true,\"isRequired\":true,\"isUnique\":false,\"isId\":false,\"isReadOnly\":false,\"hasDefaultValue\":false,\"type\":\"UserRole\",\"relationName\":\"RoleToUserRole\",\"relationFromFields\":[],\"relationToFields\":[],\"isGenerated\":false,\"isUpdatedAt\":false},{\"name\":\"createdAt\",\"kind\":\"scalar\",\"isList\":false,\"isRequired\":true,\"isUnique\":false,\"isId\":false,\"isReadOnly\":false,\"hasDefaultValue\":true,\"type\":\"DateTime\",\"default\":{\"name\":\"now\",\"args\":[]},\"isGenerated\":false,\"isUpdatedAt\":false},{\"name\":\"updatedAt\",\"kind\":\"scalar\",\"isList\":false,\"isRequired\":true,\"isUnique\":false,\"isId\":false,\"isReadOnly\":false,\"hasDefaultValue\":false,\"type\":\"DateTime\",\"isGenerated\":false,\"isUpdatedAt\":true}],\"primaryKey\":null,\"uniqueFields\":[],\"uniqueIndexes\":[],\"isGenerated\":false},\"Permission\":{\"dbName\":null,\"fields\":[{\"name\":\"id\",\"kind\":\"scalar\",\"isList\":false,\"isRequired\":true,\"isUnique\":false,\"isId\":true,\"isReadOnly\":false,\"hasDefaultValue\":true,\"type\":\"Int\",\"default\":{\"name\":\"autoincrement\",\"args\":[]},\"isGenerated\":false,\"isUpdatedAt\":false},{\"name\":\"resource\",\"kind\":\"scalar\",\"isList\":false,\"isRequired\":true,\"isUnique\":false,\"isId\":false,\"isReadOnly\":false,\"hasDefaultValue\":false,\"type\":\"String\",\"isGenerated\":false,\"isUpdatedAt\":false},{\"name\":\"action\",\"kind\":\"scalar\",\"isList\":false,\"isRequired\":true,\"isUnique\":false,\"isId\":false,\"isReadOnly\":false,\"hasDefaultValue\":false,\"type\":\"String\",\"isGenerated\":false,\"isUpdatedAt\":false},{\"name\":\"roles\",\"kind\":\"object\",\"isList\":true,\"isRequired\":true,\"isUnique\":false,\"isId\":false,\"isReadOnly\":false,\"hasDefaultValue\":false,\"type\":\"RolePermission\",\"relationName\":\"PermissionToRolePermission\",\"relationFromFields\":[],\"relationToFields\":[],\"isGenerated\":false,\"isUpdatedAt\":false}],\"primaryKey\":null,\"uniqueFields\":[[\"resource\",\"action\"]],\"uniqueIndexes\":[{\"name\":null,\"fields\":[\"resource\",\"action\"]}],\"isGenerated\":false},\"RolePermission\":{\"dbName\":null,\"fields\":[{\"name\":\"roleId\",\"kind\":\"scalar\",\"isList\":false,\"isRequired\":true,\"isUnique\":false,\"isId\":false,\"isReadOnly\":true,\"hasDefaultValue\":false,\"type\":\"Int\",\"isGenerated\":false,\"isUpdatedAt\":false},{\"name\":\"permissionId\",\"kind\":\"scalar\",\"isList\":false,\"isRequired\":true,\"isUnique\":false,\"isId\":false,\"isReadOnly\":true,\"hasDefaultValue\":false,\"type\":\"Int\",\"isGenerated\":false,\"isUpdatedAt\":false},{\"name\":\"role\",\"kind\":\"object\",\"isList\":false,\"isRequired\":true,\"isUnique\":false,\"isId\":false,\"isReadOnly\":false,\"hasDefaultValue\":false,\"type\":\"Role\",\"relationName\":\"RoleToRolePermission\",\"relationFromFields\":[\"roleId\"],\"relationToFields\":[\"id\"],\"relationOnDelete\":\"Cascade\",\"isGenerated\":false,\"isUpdatedAt\":false},{\"name\":\"permission\",\"kind\":\"object\",\"isList\":false,\"isRequired\":true,\"isUnique\":false,\"isId\":false,\"isReadOnly\":false,\"hasDefaultValue\":false,\"type\":\"Permission\",\"relationName\":\"PermissionToRolePermission\",\"relationFromFields\":[\"permissionId\"],\"relationToFields\":[\"id\"],\"relationOnDelete\":\"Cascade\",\"isGenerated\":false,\"isUpdatedAt\":false}],\"primaryKey\":{\"name\":null,\"fields\":[\"roleId\",\"permissionId\"]},\"uniqueFields\":[],\"uniqueIndexes\":[],\"isGenerated\":false},\"UserRole\":{\"dbName\":null,\"fields\":[{\"name\":\"userId\",\"kind\":\"scalar\",\"isList\":false,\"isRequired\":true,\"isUnique\":false,\"isId\":false,\"isReadOnly\":true,\"hasDefaultValue\":false,\"type\":\"Int\",\"isGenerated\":false,\"isUpdatedAt\":false},{\"name\":\"roleId\",\"kind\":\"scalar\",\"isList\":false,\"isRequired\":true,\"isUnique\":false,\"isId\":false,\"isReadOnly\":true,\"hasDefaultValue\":false,\"type\":\"Int\",\"isGenerated\":false,\"isUpdatedAt\":false},{\"name\":\"user\",\"kind\":\"object\",\"isList\":false,\"isRequired\":true,\"isUnique\":false,\"isId\":false,\"isReadOnly\":false,\"hasDefaultValue\":false,\"type\":\"User\",\"relationName\":\"UserToUserRole\",\"relationFromFields\":[\"userId\"],\"relationToFields\":[\"id\"],\"relationOnDelete\":\"Cascade\",\"isGenerated\":false,\"isUpdatedAt\":false},{\"name\":\"role\",\"kind\":\"object\",\"isList\":false,\"isRequired\":true,\"isUnique\":false,\"isId\":false,\"isReadOnly\":false,\"hasDefaultValue\":false,\"type\":\"Role\",\"relationName\":\"RoleToUserRole\",\"relationFromFields\":[\"roleId\"],\"relationToFields\":[\"id\"],\"relationOnDelete\":\"Cascade\",\"isGenerated\":false,\"isUpdatedAt\":false}],\"primaryKey\":{\"name\":null,\"fields\":[\"userId\",\"roleId\"]},\"uniqueFields\":[],\"uniqueIndexes\":[],\"isGenerated\":false},\"Customer\":{\"dbName\":null,\"fields\":[{\"name\":\"id\",\"kind\":\"scalar\",\"isList\":false,\"isRequired\":true,\"isUnique\":false,\"isId\":true,\"isReadOnly\":false,\"hasDefaultValue\":true,\"type\":\"Int\",\"default\":{\"name\":\"autoincrement\",\"args\":[]},\"isGenerated\":false,\"isUpdatedAt\":false},{\"name\":\"customerNumber\",\"kind\":\"scalar\",\"isList\":false,\"isRequired\":true,\"isUnique\":true,\"isId\":false,\"isReadOnly\":false,\"hasDefaultValue\":false,\"type\":\"String\",\"isGenerated\":false,\"isUpdatedAt\":false},{\"name\":\"type\",\"kind\":\"enum\",\"isList\":false,\"isRequired\":true,\"isUnique\":false,\"isId\":false,\"isReadOnly\":false,\"hasDefaultValue\":true,\"type\":\"CustomerType\",\"default\":\"PRIVATE\",\"isGenerated\":false,\"isUpdatedAt\":false},{\"name\":\"salutation\",\"kind\":\"scalar\",\"isList\":false,\"isRequired\":false,\"isUnique\":false,\"isId\":false,\"isReadOnly\":false,\"hasDefaultValue\":false,\"type\":\"String\",\"isGenerated\":false,\"isUpdatedAt\":false},{\"name\":\"firstName\",\"kind\":\"scalar\",\"isList\":false,\"isRequired\":true,\"isUnique\":false,\"isId\":false,\"isReadOnly\":false,\"hasDefaultValue\":false,\"type\":\"String\",\"isGenerated\":false,\"isUpdatedAt\":false},{\"name\":\"lastName\",\"kind\":\"scalar\",\"isList\":false,\"isRequired\":true,\"isUnique\":false,\"isId\":false,\"isReadOnly\":false,\"hasDefaultValue\":false,\"type\":\"String\",\"isGenerated\":false,\"isUpdatedAt\":false},{\"name\":\"companyName\",\"kind\":\"scalar\",\"isList\":false,\"isRequired\":false,\"isUnique\":false,\"isId\":false,\"isReadOnly\":false,\"hasDefaultValue\":false,\"type\":\"String\",\"isGenerated\":false,\"isUpdatedAt\":false},{\"name\":\"foundingDate\",\"kind\":\"scalar\",\"isList\":false,\"isRequired\":false,\"isUnique\":false,\"isId\":false,\"isReadOnly\":false,\"hasDefaultValue\":false,\"type\":\"DateTime\",\"isGenerated\":false,\"isUpdatedAt\":false},{\"name\":\"birthDate\",\"kind\":\"scalar\",\"isList\":false,\"isRequired\":false,\"isUnique\":false,\"isId\":false,\"isReadOnly\":false,\"hasDefaultValue\":false,\"type\":\"DateTime\",\"isGenerated\":false,\"isUpdatedAt\":false},{\"name\":\"birthPlace\",\"kind\":\"scalar\",\"isList\":false,\"isRequired\":false,\"isUnique\":false,\"isId\":false,\"isReadOnly\":false,\"hasDefaultValue\":false,\"type\":\"String\",\"isGenerated\":false,\"isUpdatedAt\":false},{\"name\":\"email\",\"kind\":\"scalar\",\"isList\":false,\"isRequired\":false,\"isUnique\":false,\"isId\":false,\"isReadOnly\":false,\"hasDefaultValue\":false,\"type\":\"String\",\"isGenerated\":false,\"isUpdatedAt\":false},{\"name\":\"phone\",\"kind\":\"scalar\",\"isList\":false,\"isRequired\":false,\"isUnique\":false,\"isId\":false,\"isReadOnly\":false,\"hasDefaultValue\":false,\"type\":\"String\",\"isGenerated\":false,\"isUpdatedAt\":false},{\"name\":\"mobile\",\"kind\":\"scalar\",\"isList\":false,\"isRequired\":false,\"isUnique\":false,\"isId\":false,\"isReadOnly\":false,\"hasDefaultValue\":false,\"type\":\"String\",\"isGenerated\":false,\"isUpdatedAt\":false},{\"name\":\"taxNumber\",\"kind\":\"scalar\",\"isList\":false,\"isRequired\":false,\"isUnique\":false,\"isId\":false,\"isReadOnly\":false,\"hasDefaultValue\":false,\"type\":\"String\",\"isGenerated\":false,\"isUpdatedAt\":false},{\"name\":\"businessRegistrationPath\",\"kind\":\"scalar\",\"isList\":false,\"isRequired\":false,\"isUnique\":false,\"isId\":false,\"isReadOnly\":false,\"hasDefaultValue\":false,\"type\":\"String\",\"isGenerated\":false,\"isUpdatedAt\":false},{\"name\":\"commercialRegisterPath\",\"kind\":\"scalar\",\"isList\":false,\"isRequired\":false,\"isUnique\":false,\"isId\":false,\"isReadOnly\":false,\"hasDefaultValue\":false,\"type\":\"String\",\"isGenerated\":false,\"isUpdatedAt\":false},{\"name\":\"commercialRegisterNumber\",\"kind\":\"scalar\",\"isList\":false,\"isRequired\":false,\"isUnique\":false,\"isId\":false,\"isReadOnly\":false,\"hasDefaultValue\":false,\"type\":\"String\",\"isGenerated\":false,\"isUpdatedAt\":false},{\"name\":\"privacyPolicyPath\",\"kind\":\"scalar\",\"isList\":false,\"isRequired\":false,\"isUnique\":false,\"isId\":false,\"isReadOnly\":false,\"hasDefaultValue\":false,\"type\":\"String\",\"isGenerated\":false,\"isUpdatedAt\":false},{\"name\":\"notes\",\"kind\":\"scalar\",\"isList\":false,\"isRequired\":false,\"isUnique\":false,\"isId\":false,\"isReadOnly\":false,\"hasDefaultValue\":false,\"type\":\"String\",\"isGenerated\":false,\"isUpdatedAt\":false},{\"name\":\"portalEnabled\",\"kind\":\"scalar\",\"isList\":false,\"isRequired\":true,\"isUnique\":false,\"isId\":false,\"isReadOnly\":false,\"hasDefaultValue\":true,\"type\":\"Boolean\",\"default\":false,\"isGenerated\":false,\"isUpdatedAt\":false},{\"name\":\"portalEmail\",\"kind\":\"scalar\",\"isList\":false,\"isRequired\":false,\"isUnique\":true,\"isId\":false,\"isReadOnly\":false,\"hasDefaultValue\":false,\"type\":\"String\",\"isGenerated\":false,\"isUpdatedAt\":false},{\"name\":\"portalPasswordHash\",\"kind\":\"scalar\",\"isList\":false,\"isRequired\":false,\"isUnique\":false,\"isId\":false,\"isReadOnly\":false,\"hasDefaultValue\":false,\"type\":\"String\",\"isGenerated\":false,\"isUpdatedAt\":false},{\"name\":\"portalPasswordEncrypted\",\"kind\":\"scalar\",\"isList\":false,\"isRequired\":false,\"isUnique\":false,\"isId\":false,\"isReadOnly\":false,\"hasDefaultValue\":false,\"type\":\"String\",\"isGenerated\":false,\"isUpdatedAt\":false},{\"name\":\"portalLastLogin\",\"kind\":\"scalar\",\"isList\":false,\"isRequired\":false,\"isUnique\":false,\"isId\":false,\"isReadOnly\":false,\"hasDefaultValue\":false,\"type\":\"DateTime\",\"isGenerated\":false,\"isUpdatedAt\":false},{\"name\":\"user\",\"kind\":\"object\",\"isList\":false,\"isRequired\":false,\"isUnique\":false,\"isId\":false,\"isReadOnly\":false,\"hasDefaultValue\":false,\"type\":\"User\",\"relationName\":\"CustomerToUser\",\"relationFromFields\":[],\"relationToFields\":[],\"isGenerated\":false,\"isUpdatedAt\":false},{\"name\":\"addresses\",\"kind\":\"object\",\"isList\":true,\"isRequired\":true,\"isUnique\":false,\"isId\":false,\"isReadOnly\":false,\"hasDefaultValue\":false,\"type\":\"Address\",\"relationName\":\"AddressToCustomer\",\"relationFromFields\":[],\"relationToFields\":[],\"isGenerated\":false,\"isUpdatedAt\":false},{\"name\":\"bankCards\",\"kind\":\"object\",\"isList\":true,\"isRequired\":true,\"isUnique\":false,\"isId\":false,\"isReadOnly\":false,\"hasDefaultValue\":false,\"type\":\"BankCard\",\"relationName\":\"BankCardToCustomer\",\"relationFromFields\":[],\"relationToFields\":[],\"isGenerated\":false,\"isUpdatedAt\":false},{\"name\":\"identityDocuments\",\"kind\":\"object\",\"isList\":true,\"isRequired\":true,\"isUnique\":false,\"isId\":false,\"isReadOnly\":false,\"hasDefaultValue\":false,\"type\":\"IdentityDocument\",\"relationName\":\"CustomerToIdentityDocument\",\"relationFromFields\":[],\"relationToFields\":[],\"isGenerated\":false,\"isUpdatedAt\":false},{\"name\":\"meters\",\"kind\":\"object\",\"isList\":true,\"isRequired\":true,\"isUnique\":false,\"isId\":false,\"isReadOnly\":false,\"hasDefaultValue\":false,\"type\":\"Meter\",\"relationName\":\"CustomerToMeter\",\"relationFromFields\":[],\"relationToFields\":[],\"isGenerated\":false,\"isUpdatedAt\":false},{\"name\":\"stressfreiEmails\",\"kind\":\"object\",\"isList\":true,\"isRequired\":true,\"isUnique\":false,\"isId\":false,\"isReadOnly\":false,\"hasDefaultValue\":false,\"type\":\"StressfreiEmail\",\"relationName\":\"CustomerToStressfreiEmail\",\"relationFromFields\":[],\"relationToFields\":[],\"isGenerated\":false,\"isUpdatedAt\":false},{\"name\":\"contracts\",\"kind\":\"object\",\"isList\":true,\"isRequired\":true,\"isUnique\":false,\"isId\":false,\"isReadOnly\":false,\"hasDefaultValue\":false,\"type\":\"Contract\",\"relationName\":\"ContractToCustomer\",\"relationFromFields\":[],\"relationToFields\":[],\"isGenerated\":false,\"isUpdatedAt\":false},{\"name\":\"representingFor\",\"kind\":\"object\",\"isList\":true,\"isRequired\":true,\"isUnique\":false,\"isId\":false,\"isReadOnly\":false,\"hasDefaultValue\":false,\"type\":\"CustomerRepresentative\",\"relationName\":\"RepresentativeCustomer\",\"relationFromFields\":[],\"relationToFields\":[],\"isGenerated\":false,\"isUpdatedAt\":false},{\"name\":\"representedBy\",\"kind\":\"object\",\"isList\":true,\"isRequired\":true,\"isUnique\":false,\"isId\":false,\"isReadOnly\":false,\"hasDefaultValue\":false,\"type\":\"CustomerRepresentative\",\"relationName\":\"RepresentedCustomer\",\"relationFromFields\":[],\"relationToFields\":[],\"isGenerated\":false,\"isUpdatedAt\":false},{\"name\":\"createdAt\",\"kind\":\"scalar\",\"isList\":false,\"isRequired\":true,\"isUnique\":false,\"isId\":false,\"isReadOnly\":false,\"hasDefaultValue\":true,\"type\":\"DateTime\",\"default\":{\"name\":\"now\",\"args\":[]},\"isGenerated\":false,\"isUpdatedAt\":false},{\"name\":\"updatedAt\",\"kind\":\"scalar\",\"isList\":false,\"isRequired\":true,\"isUnique\":false,\"isId\":false,\"isReadOnly\":false,\"hasDefaultValue\":false,\"type\":\"DateTime\",\"isGenerated\":false,\"isUpdatedAt\":true}],\"primaryKey\":null,\"uniqueFields\":[],\"uniqueIndexes\":[],\"isGenerated\":false},\"CustomerRepresentative\":{\"dbName\":null,\"fields\":[{\"name\":\"id\",\"kind\":\"scalar\",\"isList\":false,\"isRequired\":true,\"isUnique\":false,\"isId\":true,\"isReadOnly\":false,\"hasDefaultValue\":true,\"type\":\"Int\",\"default\":{\"name\":\"autoincrement\",\"args\":[]},\"isGenerated\":false,\"isUpdatedAt\":false},{\"name\":\"customerId\",\"kind\":\"scalar\",\"isList\":false,\"isRequired\":true,\"isUnique\":false,\"isId\":false,\"isReadOnly\":true,\"hasDefaultValue\":false,\"type\":\"Int\",\"isGenerated\":false,\"isUpdatedAt\":false},{\"name\":\"customer\",\"kind\":\"object\",\"isList\":false,\"isRequired\":true,\"isUnique\":false,\"isId\":false,\"isReadOnly\":false,\"hasDefaultValue\":false,\"type\":\"Customer\",\"relationName\":\"RepresentedCustomer\",\"relationFromFields\":[\"customerId\"],\"relationToFields\":[\"id\"],\"relationOnDelete\":\"Cascade\",\"isGenerated\":false,\"isUpdatedAt\":false},{\"name\":\"representativeId\",\"kind\":\"scalar\",\"isList\":false,\"isRequired\":true,\"isUnique\":false,\"isId\":false,\"isReadOnly\":true,\"hasDefaultValue\":false,\"type\":\"Int\",\"isGenerated\":false,\"isUpdatedAt\":false},{\"name\":\"representative\",\"kind\":\"object\",\"isList\":false,\"isRequired\":true,\"isUnique\":false,\"isId\":false,\"isReadOnly\":false,\"hasDefaultValue\":false,\"type\":\"Customer\",\"relationName\":\"RepresentativeCustomer\",\"relationFromFields\":[\"representativeId\"],\"relationToFields\":[\"id\"],\"relationOnDelete\":\"Cascade\",\"isGenerated\":false,\"isUpdatedAt\":false},{\"name\":\"notes\",\"kind\":\"scalar\",\"isList\":false,\"isRequired\":false,\"isUnique\":false,\"isId\":false,\"isReadOnly\":false,\"hasDefaultValue\":false,\"type\":\"String\",\"isGenerated\":false,\"isUpdatedAt\":false},{\"name\":\"isActive\",\"kind\":\"scalar\",\"isList\":false,\"isRequired\":true,\"isUnique\":false,\"isId\":false,\"isReadOnly\":false,\"hasDefaultValue\":true,\"type\":\"Boolean\",\"default\":true,\"isGenerated\":false,\"isUpdatedAt\":false},{\"name\":\"createdAt\",\"kind\":\"scalar\",\"isList\":false,\"isRequired\":true,\"isUnique\":false,\"isId\":false,\"isReadOnly\":false,\"hasDefaultValue\":true,\"type\":\"DateTime\",\"default\":{\"name\":\"now\",\"args\":[]},\"isGenerated\":false,\"isUpdatedAt\":false},{\"name\":\"updatedAt\",\"kind\":\"scalar\",\"isList\":false,\"isRequired\":true,\"isUnique\":false,\"isId\":false,\"isReadOnly\":false,\"hasDefaultValue\":false,\"type\":\"DateTime\",\"isGenerated\":false,\"isUpdatedAt\":true}],\"primaryKey\":null,\"uniqueFields\":[[\"customerId\",\"representativeId\"]],\"uniqueIndexes\":[{\"name\":null,\"fields\":[\"customerId\",\"representativeId\"]}],\"isGenerated\":false},\"Address\":{\"dbName\":null,\"fields\":[{\"name\":\"id\",\"kind\":\"scalar\",\"isList\":false,\"isRequired\":true,\"isUnique\":false,\"isId\":true,\"isReadOnly\":false,\"hasDefaultValue\":true,\"type\":\"Int\",\"default\":{\"name\":\"autoincrement\",\"args\":[]},\"isGenerated\":false,\"isUpdatedAt\":false},{\"name\":\"customerId\",\"kind\":\"scalar\",\"isList\":false,\"isRequired\":true,\"isUnique\":false,\"isId\":false,\"isReadOnly\":true,\"hasDefaultValue\":false,\"type\":\"Int\",\"isGenerated\":false,\"isUpdatedAt\":false},{\"name\":\"customer\",\"kind\":\"object\",\"isList\":false,\"isRequired\":true,\"isUnique\":false,\"isId\":false,\"isReadOnly\":false,\"hasDefaultValue\":false,\"type\":\"Customer\",\"relationName\":\"AddressToCustomer\",\"relationFromFields\":[\"customerId\"],\"relationToFields\":[\"id\"],\"relationOnDelete\":\"Cascade\",\"isGenerated\":false,\"isUpdatedAt\":false},{\"name\":\"type\",\"kind\":\"enum\",\"isList\":false,\"isRequired\":true,\"isUnique\":false,\"isId\":false,\"isReadOnly\":false,\"hasDefaultValue\":true,\"type\":\"AddressType\",\"default\":\"DELIVERY_RESIDENCE\",\"isGenerated\":false,\"isUpdatedAt\":false},{\"name\":\"street\",\"kind\":\"scalar\",\"isList\":false,\"isRequired\":true,\"isUnique\":false,\"isId\":false,\"isReadOnly\":false,\"hasDefaultValue\":false,\"type\":\"String\",\"isGenerated\":false,\"isUpdatedAt\":false},{\"name\":\"houseNumber\",\"kind\":\"scalar\",\"isList\":false,\"isRequired\":true,\"isUnique\":false,\"isId\":false,\"isReadOnly\":false,\"hasDefaultValue\":false,\"type\":\"String\",\"isGenerated\":false,\"isUpdatedAt\":false},{\"name\":\"postalCode\",\"kind\":\"scalar\",\"isList\":false,\"isRequired\":true,\"isUnique\":false,\"isId\":false,\"isReadOnly\":false,\"hasDefaultValue\":false,\"type\":\"String\",\"isGenerated\":false,\"isUpdatedAt\":false},{\"name\":\"city\",\"kind\":\"scalar\",\"isList\":false,\"isRequired\":true,\"isUnique\":false,\"isId\":false,\"isReadOnly\":false,\"hasDefaultValue\":false,\"type\":\"String\",\"isGenerated\":false,\"isUpdatedAt\":false},{\"name\":\"country\",\"kind\":\"scalar\",\"isList\":false,\"isRequired\":true,\"isUnique\":false,\"isId\":false,\"isReadOnly\":false,\"hasDefaultValue\":true,\"type\":\"String\",\"default\":\"Deutschland\",\"isGenerated\":false,\"isUpdatedAt\":false},{\"name\":\"isDefault\",\"kind\":\"scalar\",\"isList\":false,\"isRequired\":true,\"isUnique\":false,\"isId\":false,\"isReadOnly\":false,\"hasDefaultValue\":true,\"type\":\"Boolean\",\"default\":false,\"isGenerated\":false,\"isUpdatedAt\":false},{\"name\":\"contracts\",\"kind\":\"object\",\"isList\":true,\"isRequired\":true,\"isUnique\":false,\"isId\":false,\"isReadOnly\":false,\"hasDefaultValue\":false,\"type\":\"Contract\",\"relationName\":\"AddressToContract\",\"relationFromFields\":[],\"relationToFields\":[],\"isGenerated\":false,\"isUpdatedAt\":false},{\"name\":\"createdAt\",\"kind\":\"scalar\",\"isList\":false,\"isRequired\":true,\"isUnique\":false,\"isId\":false,\"isReadOnly\":false,\"hasDefaultValue\":true,\"type\":\"DateTime\",\"default\":{\"name\":\"now\",\"args\":[]},\"isGenerated\":false,\"isUpdatedAt\":false},{\"name\":\"updatedAt\",\"kind\":\"scalar\",\"isList\":false,\"isRequired\":true,\"isUnique\":false,\"isId\":false,\"isReadOnly\":false,\"hasDefaultValue\":false,\"type\":\"DateTime\",\"isGenerated\":false,\"isUpdatedAt\":true}],\"primaryKey\":null,\"uniqueFields\":[],\"uniqueIndexes\":[],\"isGenerated\":false},\"BankCard\":{\"dbName\":null,\"fields\":[{\"name\":\"id\",\"kind\":\"scalar\",\"isList\":false,\"isRequired\":true,\"isUnique\":false,\"isId\":true,\"isReadOnly\":false,\"hasDefaultValue\":true,\"type\":\"Int\",\"default\":{\"name\":\"autoincrement\",\"args\":[]},\"isGenerated\":false,\"isUpdatedAt\":false},{\"name\":\"customerId\",\"kind\":\"scalar\",\"isList\":false,\"isRequired\":true,\"isUnique\":false,\"isId\":false,\"isReadOnly\":true,\"hasDefaultValue\":false,\"type\":\"Int\",\"isGenerated\":false,\"isUpdatedAt\":false},{\"name\":\"customer\",\"kind\":\"object\",\"isList\":false,\"isRequired\":true,\"isUnique\":false,\"isId\":false,\"isReadOnly\":false,\"hasDefaultValue\":false,\"type\":\"Customer\",\"relationName\":\"BankCardToCustomer\",\"relationFromFields\":[\"customerId\"],\"relationToFields\":[\"id\"],\"relationOnDelete\":\"Cascade\",\"isGenerated\":false,\"isUpdatedAt\":false},{\"name\":\"accountHolder\",\"kind\":\"scalar\",\"isList\":false,\"isRequired\":true,\"isUnique\":false,\"isId\":false,\"isReadOnly\":false,\"hasDefaultValue\":false,\"type\":\"String\",\"isGenerated\":false,\"isUpdatedAt\":false},{\"name\":\"iban\",\"kind\":\"scalar\",\"isList\":false,\"isRequired\":true,\"isUnique\":false,\"isId\":false,\"isReadOnly\":false,\"hasDefaultValue\":false,\"type\":\"String\",\"isGenerated\":false,\"isUpdatedAt\":false},{\"name\":\"bic\",\"kind\":\"scalar\",\"isList\":false,\"isRequired\":false,\"isUnique\":false,\"isId\":false,\"isReadOnly\":false,\"hasDefaultValue\":false,\"type\":\"String\",\"isGenerated\":false,\"isUpdatedAt\":false},{\"name\":\"bankName\",\"kind\":\"scalar\",\"isList\":false,\"isRequired\":false,\"isUnique\":false,\"isId\":false,\"isReadOnly\":false,\"hasDefaultValue\":false,\"type\":\"String\",\"isGenerated\":false,\"isUpdatedAt\":false},{\"name\":\"expiryDate\",\"kind\":\"scalar\",\"isList\":false,\"isRequired\":false,\"isUnique\":false,\"isId\":false,\"isReadOnly\":false,\"hasDefaultValue\":false,\"type\":\"DateTime\",\"isGenerated\":false,\"isUpdatedAt\":false},{\"name\":\"documentPath\",\"kind\":\"scalar\",\"isList\":false,\"isRequired\":false,\"isUnique\":false,\"isId\":false,\"isReadOnly\":false,\"hasDefaultValue\":false,\"type\":\"String\",\"isGenerated\":false,\"isUpdatedAt\":false},{\"name\":\"isActive\",\"kind\":\"scalar\",\"isList\":false,\"isRequired\":true,\"isUnique\":false,\"isId\":false,\"isReadOnly\":false,\"hasDefaultValue\":true,\"type\":\"Boolean\",\"default\":true,\"isGenerated\":false,\"isUpdatedAt\":false},{\"name\":\"contracts\",\"kind\":\"object\",\"isList\":true,\"isRequired\":true,\"isUnique\":false,\"isId\":false,\"isReadOnly\":false,\"hasDefaultValue\":false,\"type\":\"Contract\",\"relationName\":\"BankCardToContract\",\"relationFromFields\":[],\"relationToFields\":[],\"isGenerated\":false,\"isUpdatedAt\":false},{\"name\":\"createdAt\",\"kind\":\"scalar\",\"isList\":false,\"isRequired\":true,\"isUnique\":false,\"isId\":false,\"isReadOnly\":false,\"hasDefaultValue\":true,\"type\":\"DateTime\",\"default\":{\"name\":\"now\",\"args\":[]},\"isGenerated\":false,\"isUpdatedAt\":false},{\"name\":\"updatedAt\",\"kind\":\"scalar\",\"isList\":false,\"isRequired\":true,\"isUnique\":false,\"isId\":false,\"isReadOnly\":false,\"hasDefaultValue\":false,\"type\":\"DateTime\",\"isGenerated\":false,\"isUpdatedAt\":true}],\"primaryKey\":null,\"uniqueFields\":[],\"uniqueIndexes\":[],\"isGenerated\":false},\"IdentityDocument\":{\"dbName\":null,\"fields\":[{\"name\":\"id\",\"kind\":\"scalar\",\"isList\":false,\"isRequired\":true,\"isUnique\":false,\"isId\":true,\"isReadOnly\":false,\"hasDefaultValue\":true,\"type\":\"Int\",\"default\":{\"name\":\"autoincrement\",\"args\":[]},\"isGenerated\":false,\"isUpdatedAt\":false},{\"name\":\"customerId\",\"kind\":\"scalar\",\"isList\":false,\"isRequired\":true,\"isUnique\":false,\"isId\":false,\"isReadOnly\":true,\"hasDefaultValue\":false,\"type\":\"Int\",\"isGenerated\":false,\"isUpdatedAt\":false},{\"name\":\"customer\",\"kind\":\"object\",\"isList\":false,\"isRequired\":true,\"isUnique\":false,\"isId\":false,\"isReadOnly\":false,\"hasDefaultValue\":false,\"type\":\"Customer\",\"relationName\":\"CustomerToIdentityDocument\",\"relationFromFields\":[\"customerId\"],\"relationToFields\":[\"id\"],\"relationOnDelete\":\"Cascade\",\"isGenerated\":false,\"isUpdatedAt\":false},{\"name\":\"type\",\"kind\":\"enum\",\"isList\":false,\"isRequired\":true,\"isUnique\":false,\"isId\":false,\"isReadOnly\":false,\"hasDefaultValue\":true,\"type\":\"DocumentType\",\"default\":\"ID_CARD\",\"isGenerated\":false,\"isUpdatedAt\":false},{\"name\":\"documentNumber\",\"kind\":\"scalar\",\"isList\":false,\"isRequired\":true,\"isUnique\":false,\"isId\":false,\"isReadOnly\":false,\"hasDefaultValue\":false,\"type\":\"String\",\"isGenerated\":false,\"isUpdatedAt\":false},{\"name\":\"issuingAuthority\",\"kind\":\"scalar\",\"isList\":false,\"isRequired\":false,\"isUnique\":false,\"isId\":false,\"isReadOnly\":false,\"hasDefaultValue\":false,\"type\":\"String\",\"isGenerated\":false,\"isUpdatedAt\":false},{\"name\":\"issueDate\",\"kind\":\"scalar\",\"isList\":false,\"isRequired\":false,\"isUnique\":false,\"isId\":false,\"isReadOnly\":false,\"hasDefaultValue\":false,\"type\":\"DateTime\",\"isGenerated\":false,\"isUpdatedAt\":false},{\"name\":\"expiryDate\",\"kind\":\"scalar\",\"isList\":false,\"isRequired\":false,\"isUnique\":false,\"isId\":false,\"isReadOnly\":false,\"hasDefaultValue\":false,\"type\":\"DateTime\",\"isGenerated\":false,\"isUpdatedAt\":false},{\"name\":\"documentPath\",\"kind\":\"scalar\",\"isList\":false,\"isRequired\":false,\"isUnique\":false,\"isId\":false,\"isReadOnly\":false,\"hasDefaultValue\":false,\"type\":\"String\",\"isGenerated\":false,\"isUpdatedAt\":false},{\"name\":\"isActive\",\"kind\":\"scalar\",\"isList\":false,\"isRequired\":true,\"isUnique\":false,\"isId\":false,\"isReadOnly\":false,\"hasDefaultValue\":true,\"type\":\"Boolean\",\"default\":true,\"isGenerated\":false,\"isUpdatedAt\":false},{\"name\":\"licenseClasses\",\"kind\":\"scalar\",\"isList\":false,\"isRequired\":false,\"isUnique\":false,\"isId\":false,\"isReadOnly\":false,\"hasDefaultValue\":false,\"type\":\"String\",\"isGenerated\":false,\"isUpdatedAt\":false},{\"name\":\"licenseIssueDate\",\"kind\":\"scalar\",\"isList\":false,\"isRequired\":false,\"isUnique\":false,\"isId\":false,\"isReadOnly\":false,\"hasDefaultValue\":false,\"type\":\"DateTime\",\"isGenerated\":false,\"isUpdatedAt\":false},{\"name\":\"contracts\",\"kind\":\"object\",\"isList\":true,\"isRequired\":true,\"isUnique\":false,\"isId\":false,\"isReadOnly\":false,\"hasDefaultValue\":false,\"type\":\"Contract\",\"relationName\":\"ContractToIdentityDocument\",\"relationFromFields\":[],\"relationToFields\":[],\"isGenerated\":false,\"isUpdatedAt\":false},{\"name\":\"createdAt\",\"kind\":\"scalar\",\"isList\":false,\"isRequired\":true,\"isUnique\":false,\"isId\":false,\"isReadOnly\":false,\"hasDefaultValue\":true,\"type\":\"DateTime\",\"default\":{\"name\":\"now\",\"args\":[]},\"isGenerated\":false,\"isUpdatedAt\":false},{\"name\":\"updatedAt\",\"kind\":\"scalar\",\"isList\":false,\"isRequired\":true,\"isUnique\":false,\"isId\":false,\"isReadOnly\":false,\"hasDefaultValue\":false,\"type\":\"DateTime\",\"isGenerated\":false,\"isUpdatedAt\":true}],\"primaryKey\":null,\"uniqueFields\":[],\"uniqueIndexes\":[],\"isGenerated\":false},\"EmailProviderConfig\":{\"dbName\":null,\"fields\":[{\"name\":\"id\",\"kind\":\"scalar\",\"isList\":false,\"isRequired\":true,\"isUnique\":false,\"isId\":true,\"isReadOnly\":false,\"hasDefaultValue\":true,\"type\":\"Int\",\"default\":{\"name\":\"autoincrement\",\"args\":[]},\"isGenerated\":false,\"isUpdatedAt\":false},{\"name\":\"name\",\"kind\":\"scalar\",\"isList\":false,\"isRequired\":true,\"isUnique\":true,\"isId\":false,\"isReadOnly\":false,\"hasDefaultValue\":false,\"type\":\"String\",\"isGenerated\":false,\"isUpdatedAt\":false},{\"name\":\"type\",\"kind\":\"enum\",\"isList\":false,\"isRequired\":true,\"isUnique\":false,\"isId\":false,\"isReadOnly\":false,\"hasDefaultValue\":false,\"type\":\"EmailProviderType\",\"isGenerated\":false,\"isUpdatedAt\":false},{\"name\":\"apiUrl\",\"kind\":\"scalar\",\"isList\":false,\"isRequired\":true,\"isUnique\":false,\"isId\":false,\"isReadOnly\":false,\"hasDefaultValue\":false,\"type\":\"String\",\"isGenerated\":false,\"isUpdatedAt\":false},{\"name\":\"apiKey\",\"kind\":\"scalar\",\"isList\":false,\"isRequired\":false,\"isUnique\":false,\"isId\":false,\"isReadOnly\":false,\"hasDefaultValue\":false,\"type\":\"String\",\"isGenerated\":false,\"isUpdatedAt\":false},{\"name\":\"username\",\"kind\":\"scalar\",\"isList\":false,\"isRequired\":false,\"isUnique\":false,\"isId\":false,\"isReadOnly\":false,\"hasDefaultValue\":false,\"type\":\"String\",\"isGenerated\":false,\"isUpdatedAt\":false},{\"name\":\"passwordEncrypted\",\"kind\":\"scalar\",\"isList\":false,\"isRequired\":false,\"isUnique\":false,\"isId\":false,\"isReadOnly\":false,\"hasDefaultValue\":false,\"type\":\"String\",\"isGenerated\":false,\"isUpdatedAt\":false},{\"name\":\"domain\",\"kind\":\"scalar\",\"isList\":false,\"isRequired\":true,\"isUnique\":false,\"isId\":false,\"isReadOnly\":false,\"hasDefaultValue\":false,\"type\":\"String\",\"isGenerated\":false,\"isUpdatedAt\":false},{\"name\":\"defaultForwardEmail\",\"kind\":\"scalar\",\"isList\":false,\"isRequired\":false,\"isUnique\":false,\"isId\":false,\"isReadOnly\":false,\"hasDefaultValue\":false,\"type\":\"String\",\"isGenerated\":false,\"isUpdatedAt\":false},{\"name\":\"isActive\",\"kind\":\"scalar\",\"isList\":false,\"isRequired\":true,\"isUnique\":false,\"isId\":false,\"isReadOnly\":false,\"hasDefaultValue\":true,\"type\":\"Boolean\",\"default\":true,\"isGenerated\":false,\"isUpdatedAt\":false},{\"name\":\"isDefault\",\"kind\":\"scalar\",\"isList\":false,\"isRequired\":true,\"isUnique\":false,\"isId\":false,\"isReadOnly\":false,\"hasDefaultValue\":true,\"type\":\"Boolean\",\"default\":false,\"isGenerated\":false,\"isUpdatedAt\":false},{\"name\":\"createdAt\",\"kind\":\"scalar\",\"isList\":false,\"isRequired\":true,\"isUnique\":false,\"isId\":false,\"isReadOnly\":false,\"hasDefaultValue\":true,\"type\":\"DateTime\",\"default\":{\"name\":\"now\",\"args\":[]},\"isGenerated\":false,\"isUpdatedAt\":false},{\"name\":\"updatedAt\",\"kind\":\"scalar\",\"isList\":false,\"isRequired\":true,\"isUnique\":false,\"isId\":false,\"isReadOnly\":false,\"hasDefaultValue\":false,\"type\":\"DateTime\",\"isGenerated\":false,\"isUpdatedAt\":true}],\"primaryKey\":null,\"uniqueFields\":[],\"uniqueIndexes\":[],\"isGenerated\":false},\"StressfreiEmail\":{\"dbName\":null,\"fields\":[{\"name\":\"id\",\"kind\":\"scalar\",\"isList\":false,\"isRequired\":true,\"isUnique\":false,\"isId\":true,\"isReadOnly\":false,\"hasDefaultValue\":true,\"type\":\"Int\",\"default\":{\"name\":\"autoincrement\",\"args\":[]},\"isGenerated\":false,\"isUpdatedAt\":false},{\"name\":\"customerId\",\"kind\":\"scalar\",\"isList\":false,\"isRequired\":true,\"isUnique\":false,\"isId\":false,\"isReadOnly\":true,\"hasDefaultValue\":false,\"type\":\"Int\",\"isGenerated\":false,\"isUpdatedAt\":false},{\"name\":\"customer\",\"kind\":\"object\",\"isList\":false,\"isRequired\":true,\"isUnique\":false,\"isId\":false,\"isReadOnly\":false,\"hasDefaultValue\":false,\"type\":\"Customer\",\"relationName\":\"CustomerToStressfreiEmail\",\"relationFromFields\":[\"customerId\"],\"relationToFields\":[\"id\"],\"relationOnDelete\":\"Cascade\",\"isGenerated\":false,\"isUpdatedAt\":false},{\"name\":\"email\",\"kind\":\"scalar\",\"isList\":false,\"isRequired\":true,\"isUnique\":false,\"isId\":false,\"isReadOnly\":false,\"hasDefaultValue\":false,\"type\":\"String\",\"isGenerated\":false,\"isUpdatedAt\":false},{\"name\":\"platform\",\"kind\":\"scalar\",\"isList\":false,\"isRequired\":false,\"isUnique\":false,\"isId\":false,\"isReadOnly\":false,\"hasDefaultValue\":false,\"type\":\"String\",\"isGenerated\":false,\"isUpdatedAt\":false},{\"name\":\"notes\",\"kind\":\"scalar\",\"isList\":false,\"isRequired\":false,\"isUnique\":false,\"isId\":false,\"isReadOnly\":false,\"hasDefaultValue\":false,\"type\":\"String\",\"isGenerated\":false,\"isUpdatedAt\":false},{\"name\":\"isActive\",\"kind\":\"scalar\",\"isList\":false,\"isRequired\":true,\"isUnique\":false,\"isId\":false,\"isReadOnly\":false,\"hasDefaultValue\":true,\"type\":\"Boolean\",\"default\":true,\"isGenerated\":false,\"isUpdatedAt\":false},{\"name\":\"isProvisioned\",\"kind\":\"scalar\",\"isList\":false,\"isRequired\":true,\"isUnique\":false,\"isId\":false,\"isReadOnly\":false,\"hasDefaultValue\":true,\"type\":\"Boolean\",\"default\":false,\"isGenerated\":false,\"isUpdatedAt\":false},{\"name\":\"provisionedAt\",\"kind\":\"scalar\",\"isList\":false,\"isRequired\":false,\"isUnique\":false,\"isId\":false,\"isReadOnly\":false,\"hasDefaultValue\":false,\"type\":\"DateTime\",\"isGenerated\":false,\"isUpdatedAt\":false},{\"name\":\"provisionError\",\"kind\":\"scalar\",\"isList\":false,\"isRequired\":false,\"isUnique\":false,\"isId\":false,\"isReadOnly\":false,\"hasDefaultValue\":false,\"type\":\"String\",\"isGenerated\":false,\"isUpdatedAt\":false},{\"name\":\"contracts\",\"kind\":\"object\",\"isList\":true,\"isRequired\":true,\"isUnique\":false,\"isId\":false,\"isReadOnly\":false,\"hasDefaultValue\":false,\"type\":\"Contract\",\"relationName\":\"ContractToStressfreiEmail\",\"relationFromFields\":[],\"relationToFields\":[],\"isGenerated\":false,\"isUpdatedAt\":false},{\"name\":\"createdAt\",\"kind\":\"scalar\",\"isList\":false,\"isRequired\":true,\"isUnique\":false,\"isId\":false,\"isReadOnly\":false,\"hasDefaultValue\":true,\"type\":\"DateTime\",\"default\":{\"name\":\"now\",\"args\":[]},\"isGenerated\":false,\"isUpdatedAt\":false},{\"name\":\"updatedAt\",\"kind\":\"scalar\",\"isList\":false,\"isRequired\":true,\"isUnique\":false,\"isId\":false,\"isReadOnly\":false,\"hasDefaultValue\":false,\"type\":\"DateTime\",\"isGenerated\":false,\"isUpdatedAt\":true}],\"primaryKey\":null,\"uniqueFields\":[],\"uniqueIndexes\":[],\"isGenerated\":false},\"Meter\":{\"dbName\":null,\"fields\":[{\"name\":\"id\",\"kind\":\"scalar\",\"isList\":false,\"isRequired\":true,\"isUnique\":false,\"isId\":true,\"isReadOnly\":false,\"hasDefaultValue\":true,\"type\":\"Int\",\"default\":{\"name\":\"autoincrement\",\"args\":[]},\"isGenerated\":false,\"isUpdatedAt\":false},{\"name\":\"customerId\",\"kind\":\"scalar\",\"isList\":false,\"isRequired\":true,\"isUnique\":false,\"isId\":false,\"isReadOnly\":true,\"hasDefaultValue\":false,\"type\":\"Int\",\"isGenerated\":false,\"isUpdatedAt\":false},{\"name\":\"customer\",\"kind\":\"object\",\"isList\":false,\"isRequired\":true,\"isUnique\":false,\"isId\":false,\"isReadOnly\":false,\"hasDefaultValue\":false,\"type\":\"Customer\",\"relationName\":\"CustomerToMeter\",\"relationFromFields\":[\"customerId\"],\"relationToFields\":[\"id\"],\"relationOnDelete\":\"Cascade\",\"isGenerated\":false,\"isUpdatedAt\":false},{\"name\":\"meterNumber\",\"kind\":\"scalar\",\"isList\":false,\"isRequired\":true,\"isUnique\":false,\"isId\":false,\"isReadOnly\":false,\"hasDefaultValue\":false,\"type\":\"String\",\"isGenerated\":false,\"isUpdatedAt\":false},{\"name\":\"type\",\"kind\":\"enum\",\"isList\":false,\"isRequired\":true,\"isUnique\":false,\"isId\":false,\"isReadOnly\":false,\"hasDefaultValue\":false,\"type\":\"MeterType\",\"isGenerated\":false,\"isUpdatedAt\":false},{\"name\":\"location\",\"kind\":\"scalar\",\"isList\":false,\"isRequired\":false,\"isUnique\":false,\"isId\":false,\"isReadOnly\":false,\"hasDefaultValue\":false,\"type\":\"String\",\"isGenerated\":false,\"isUpdatedAt\":false},{\"name\":\"isActive\",\"kind\":\"scalar\",\"isList\":false,\"isRequired\":true,\"isUnique\":false,\"isId\":false,\"isReadOnly\":false,\"hasDefaultValue\":true,\"type\":\"Boolean\",\"default\":true,\"isGenerated\":false,\"isUpdatedAt\":false},{\"name\":\"readings\",\"kind\":\"object\",\"isList\":true,\"isRequired\":true,\"isUnique\":false,\"isId\":false,\"isReadOnly\":false,\"hasDefaultValue\":false,\"type\":\"MeterReading\",\"relationName\":\"MeterToMeterReading\",\"relationFromFields\":[],\"relationToFields\":[],\"isGenerated\":false,\"isUpdatedAt\":false},{\"name\":\"energyDetails\",\"kind\":\"object\",\"isList\":true,\"isRequired\":true,\"isUnique\":false,\"isId\":false,\"isReadOnly\":false,\"hasDefaultValue\":false,\"type\":\"EnergyContractDetails\",\"relationName\":\"EnergyContractDetailsToMeter\",\"relationFromFields\":[],\"relationToFields\":[],\"isGenerated\":false,\"isUpdatedAt\":false},{\"name\":\"createdAt\",\"kind\":\"scalar\",\"isList\":false,\"isRequired\":true,\"isUnique\":false,\"isId\":false,\"isReadOnly\":false,\"hasDefaultValue\":true,\"type\":\"DateTime\",\"default\":{\"name\":\"now\",\"args\":[]},\"isGenerated\":false,\"isUpdatedAt\":false},{\"name\":\"updatedAt\",\"kind\":\"scalar\",\"isList\":false,\"isRequired\":true,\"isUnique\":false,\"isId\":false,\"isReadOnly\":false,\"hasDefaultValue\":false,\"type\":\"DateTime\",\"isGenerated\":false,\"isUpdatedAt\":true}],\"primaryKey\":null,\"uniqueFields\":[],\"uniqueIndexes\":[],\"isGenerated\":false},\"MeterReading\":{\"dbName\":null,\"fields\":[{\"name\":\"id\",\"kind\":\"scalar\",\"isList\":false,\"isRequired\":true,\"isUnique\":false,\"isId\":true,\"isReadOnly\":false,\"hasDefaultValue\":true,\"type\":\"Int\",\"default\":{\"name\":\"autoincrement\",\"args\":[]},\"isGenerated\":false,\"isUpdatedAt\":false},{\"name\":\"meterId\",\"kind\":\"scalar\",\"isList\":false,\"isRequired\":true,\"isUnique\":false,\"isId\":false,\"isReadOnly\":true,\"hasDefaultValue\":false,\"type\":\"Int\",\"isGenerated\":false,\"isUpdatedAt\":false},{\"name\":\"meter\",\"kind\":\"object\",\"isList\":false,\"isRequired\":true,\"isUnique\":false,\"isId\":false,\"isReadOnly\":false,\"hasDefaultValue\":false,\"type\":\"Meter\",\"relationName\":\"MeterToMeterReading\",\"relationFromFields\":[\"meterId\"],\"relationToFields\":[\"id\"],\"relationOnDelete\":\"Cascade\",\"isGenerated\":false,\"isUpdatedAt\":false},{\"name\":\"readingDate\",\"kind\":\"scalar\",\"isList\":false,\"isRequired\":true,\"isUnique\":false,\"isId\":false,\"isReadOnly\":false,\"hasDefaultValue\":false,\"type\":\"DateTime\",\"isGenerated\":false,\"isUpdatedAt\":false},{\"name\":\"value\",\"kind\":\"scalar\",\"isList\":false,\"isRequired\":true,\"isUnique\":false,\"isId\":false,\"isReadOnly\":false,\"hasDefaultValue\":false,\"type\":\"Float\",\"isGenerated\":false,\"isUpdatedAt\":false},{\"name\":\"unit\",\"kind\":\"scalar\",\"isList\":false,\"isRequired\":true,\"isUnique\":false,\"isId\":false,\"isReadOnly\":false,\"hasDefaultValue\":true,\"type\":\"String\",\"default\":\"kWh\",\"isGenerated\":false,\"isUpdatedAt\":false},{\"name\":\"notes\",\"kind\":\"scalar\",\"isList\":false,\"isRequired\":false,\"isUnique\":false,\"isId\":false,\"isReadOnly\":false,\"hasDefaultValue\":false,\"type\":\"String\",\"isGenerated\":false,\"isUpdatedAt\":false},{\"name\":\"createdAt\",\"kind\":\"scalar\",\"isList\":false,\"isRequired\":true,\"isUnique\":false,\"isId\":false,\"isReadOnly\":false,\"hasDefaultValue\":true,\"type\":\"DateTime\",\"default\":{\"name\":\"now\",\"args\":[]},\"isGenerated\":false,\"isUpdatedAt\":false}],\"primaryKey\":null,\"uniqueFields\":[],\"uniqueIndexes\":[],\"isGenerated\":false},\"SalesPlatform\":{\"dbName\":null,\"fields\":[{\"name\":\"id\",\"kind\":\"scalar\",\"isList\":false,\"isRequired\":true,\"isUnique\":false,\"isId\":true,\"isReadOnly\":false,\"hasDefaultValue\":true,\"type\":\"Int\",\"default\":{\"name\":\"autoincrement\",\"args\":[]},\"isGenerated\":false,\"isUpdatedAt\":false},{\"name\":\"name\",\"kind\":\"scalar\",\"isList\":false,\"isRequired\":true,\"isUnique\":true,\"isId\":false,\"isReadOnly\":false,\"hasDefaultValue\":false,\"type\":\"String\",\"isGenerated\":false,\"isUpdatedAt\":false},{\"name\":\"contactInfo\",\"kind\":\"scalar\",\"isList\":false,\"isRequired\":false,\"isUnique\":false,\"isId\":false,\"isReadOnly\":false,\"hasDefaultValue\":false,\"type\":\"String\",\"isGenerated\":false,\"isUpdatedAt\":false},{\"name\":\"isActive\",\"kind\":\"scalar\",\"isList\":false,\"isRequired\":true,\"isUnique\":false,\"isId\":false,\"isReadOnly\":false,\"hasDefaultValue\":true,\"type\":\"Boolean\",\"default\":true,\"isGenerated\":false,\"isUpdatedAt\":false},{\"name\":\"contracts\",\"kind\":\"object\",\"isList\":true,\"isRequired\":true,\"isUnique\":false,\"isId\":false,\"isReadOnly\":false,\"hasDefaultValue\":false,\"type\":\"Contract\",\"relationName\":\"ContractToSalesPlatform\",\"relationFromFields\":[],\"relationToFields\":[],\"isGenerated\":false,\"isUpdatedAt\":false},{\"name\":\"createdAt\",\"kind\":\"scalar\",\"isList\":false,\"isRequired\":true,\"isUnique\":false,\"isId\":false,\"isReadOnly\":false,\"hasDefaultValue\":true,\"type\":\"DateTime\",\"default\":{\"name\":\"now\",\"args\":[]},\"isGenerated\":false,\"isUpdatedAt\":false},{\"name\":\"updatedAt\",\"kind\":\"scalar\",\"isList\":false,\"isRequired\":true,\"isUnique\":false,\"isId\":false,\"isReadOnly\":false,\"hasDefaultValue\":false,\"type\":\"DateTime\",\"isGenerated\":false,\"isUpdatedAt\":true}],\"primaryKey\":null,\"uniqueFields\":[],\"uniqueIndexes\":[],\"isGenerated\":false},\"CancellationPeriod\":{\"dbName\":null,\"fields\":[{\"name\":\"id\",\"kind\":\"scalar\",\"isList\":false,\"isRequired\":true,\"isUnique\":false,\"isId\":true,\"isReadOnly\":false,\"hasDefaultValue\":true,\"type\":\"Int\",\"default\":{\"name\":\"autoincrement\",\"args\":[]},\"isGenerated\":false,\"isUpdatedAt\":false},{\"name\":\"code\",\"kind\":\"scalar\",\"isList\":false,\"isRequired\":true,\"isUnique\":true,\"isId\":false,\"isReadOnly\":false,\"hasDefaultValue\":false,\"type\":\"String\",\"isGenerated\":false,\"isUpdatedAt\":false},{\"name\":\"description\",\"kind\":\"scalar\",\"isList\":false,\"isRequired\":true,\"isUnique\":false,\"isId\":false,\"isReadOnly\":false,\"hasDefaultValue\":false,\"type\":\"String\",\"isGenerated\":false,\"isUpdatedAt\":false},{\"name\":\"isActive\",\"kind\":\"scalar\",\"isList\":false,\"isRequired\":true,\"isUnique\":false,\"isId\":false,\"isReadOnly\":false,\"hasDefaultValue\":true,\"type\":\"Boolean\",\"default\":true,\"isGenerated\":false,\"isUpdatedAt\":false},{\"name\":\"contracts\",\"kind\":\"object\",\"isList\":true,\"isRequired\":true,\"isUnique\":false,\"isId\":false,\"isReadOnly\":false,\"hasDefaultValue\":false,\"type\":\"Contract\",\"relationName\":\"CancellationPeriodToContract\",\"relationFromFields\":[],\"relationToFields\":[],\"isGenerated\":false,\"isUpdatedAt\":false},{\"name\":\"createdAt\",\"kind\":\"scalar\",\"isList\":false,\"isRequired\":true,\"isUnique\":false,\"isId\":false,\"isReadOnly\":false,\"hasDefaultValue\":true,\"type\":\"DateTime\",\"default\":{\"name\":\"now\",\"args\":[]},\"isGenerated\":false,\"isUpdatedAt\":false},{\"name\":\"updatedAt\",\"kind\":\"scalar\",\"isList\":false,\"isRequired\":true,\"isUnique\":false,\"isId\":false,\"isReadOnly\":false,\"hasDefaultValue\":false,\"type\":\"DateTime\",\"isGenerated\":false,\"isUpdatedAt\":true}],\"primaryKey\":null,\"uniqueFields\":[],\"uniqueIndexes\":[],\"isGenerated\":false},\"ContractDuration\":{\"dbName\":null,\"fields\":[{\"name\":\"id\",\"kind\":\"scalar\",\"isList\":false,\"isRequired\":true,\"isUnique\":false,\"isId\":true,\"isReadOnly\":false,\"hasDefaultValue\":true,\"type\":\"Int\",\"default\":{\"name\":\"autoincrement\",\"args\":[]},\"isGenerated\":false,\"isUpdatedAt\":false},{\"name\":\"code\",\"kind\":\"scalar\",\"isList\":false,\"isRequired\":true,\"isUnique\":true,\"isId\":false,\"isReadOnly\":false,\"hasDefaultValue\":false,\"type\":\"String\",\"isGenerated\":false,\"isUpdatedAt\":false},{\"name\":\"description\",\"kind\":\"scalar\",\"isList\":false,\"isRequired\":true,\"isUnique\":false,\"isId\":false,\"isReadOnly\":false,\"hasDefaultValue\":false,\"type\":\"String\",\"isGenerated\":false,\"isUpdatedAt\":false},{\"name\":\"isActive\",\"kind\":\"scalar\",\"isList\":false,\"isRequired\":true,\"isUnique\":false,\"isId\":false,\"isReadOnly\":false,\"hasDefaultValue\":true,\"type\":\"Boolean\",\"default\":true,\"isGenerated\":false,\"isUpdatedAt\":false},{\"name\":\"contracts\",\"kind\":\"object\",\"isList\":true,\"isRequired\":true,\"isUnique\":false,\"isId\":false,\"isReadOnly\":false,\"hasDefaultValue\":false,\"type\":\"Contract\",\"relationName\":\"ContractToContractDuration\",\"relationFromFields\":[],\"relationToFields\":[],\"isGenerated\":false,\"isUpdatedAt\":false},{\"name\":\"createdAt\",\"kind\":\"scalar\",\"isList\":false,\"isRequired\":true,\"isUnique\":false,\"isId\":false,\"isReadOnly\":false,\"hasDefaultValue\":true,\"type\":\"DateTime\",\"default\":{\"name\":\"now\",\"args\":[]},\"isGenerated\":false,\"isUpdatedAt\":false},{\"name\":\"updatedAt\",\"kind\":\"scalar\",\"isList\":false,\"isRequired\":true,\"isUnique\":false,\"isId\":false,\"isReadOnly\":false,\"hasDefaultValue\":false,\"type\":\"DateTime\",\"isGenerated\":false,\"isUpdatedAt\":true}],\"primaryKey\":null,\"uniqueFields\":[],\"uniqueIndexes\":[],\"isGenerated\":false},\"Provider\":{\"dbName\":null,\"fields\":[{\"name\":\"id\",\"kind\":\"scalar\",\"isList\":false,\"isRequired\":true,\"isUnique\":false,\"isId\":true,\"isReadOnly\":false,\"hasDefaultValue\":true,\"type\":\"Int\",\"default\":{\"name\":\"autoincrement\",\"args\":[]},\"isGenerated\":false,\"isUpdatedAt\":false},{\"name\":\"name\",\"kind\":\"scalar\",\"isList\":false,\"isRequired\":true,\"isUnique\":true,\"isId\":false,\"isReadOnly\":false,\"hasDefaultValue\":false,\"type\":\"String\",\"isGenerated\":false,\"isUpdatedAt\":false},{\"name\":\"portalUrl\",\"kind\":\"scalar\",\"isList\":false,\"isRequired\":false,\"isUnique\":false,\"isId\":false,\"isReadOnly\":false,\"hasDefaultValue\":false,\"type\":\"String\",\"isGenerated\":false,\"isUpdatedAt\":false},{\"name\":\"usernameFieldName\",\"kind\":\"scalar\",\"isList\":false,\"isRequired\":false,\"isUnique\":false,\"isId\":false,\"isReadOnly\":false,\"hasDefaultValue\":false,\"type\":\"String\",\"isGenerated\":false,\"isUpdatedAt\":false},{\"name\":\"passwordFieldName\",\"kind\":\"scalar\",\"isList\":false,\"isRequired\":false,\"isUnique\":false,\"isId\":false,\"isReadOnly\":false,\"hasDefaultValue\":false,\"type\":\"String\",\"isGenerated\":false,\"isUpdatedAt\":false},{\"name\":\"isActive\",\"kind\":\"scalar\",\"isList\":false,\"isRequired\":true,\"isUnique\":false,\"isId\":false,\"isReadOnly\":false,\"hasDefaultValue\":true,\"type\":\"Boolean\",\"default\":true,\"isGenerated\":false,\"isUpdatedAt\":false},{\"name\":\"tariffs\",\"kind\":\"object\",\"isList\":true,\"isRequired\":true,\"isUnique\":false,\"isId\":false,\"isReadOnly\":false,\"hasDefaultValue\":false,\"type\":\"Tariff\",\"relationName\":\"ProviderToTariff\",\"relationFromFields\":[],\"relationToFields\":[],\"isGenerated\":false,\"isUpdatedAt\":false},{\"name\":\"contracts\",\"kind\":\"object\",\"isList\":true,\"isRequired\":true,\"isUnique\":false,\"isId\":false,\"isReadOnly\":false,\"hasDefaultValue\":false,\"type\":\"Contract\",\"relationName\":\"ContractToProvider\",\"relationFromFields\":[],\"relationToFields\":[],\"isGenerated\":false,\"isUpdatedAt\":false},{\"name\":\"createdAt\",\"kind\":\"scalar\",\"isList\":false,\"isRequired\":true,\"isUnique\":false,\"isId\":false,\"isReadOnly\":false,\"hasDefaultValue\":true,\"type\":\"DateTime\",\"default\":{\"name\":\"now\",\"args\":[]},\"isGenerated\":false,\"isUpdatedAt\":false},{\"name\":\"updatedAt\",\"kind\":\"scalar\",\"isList\":false,\"isRequired\":true,\"isUnique\":false,\"isId\":false,\"isReadOnly\":false,\"hasDefaultValue\":false,\"type\":\"DateTime\",\"isGenerated\":false,\"isUpdatedAt\":true}],\"primaryKey\":null,\"uniqueFields\":[],\"uniqueIndexes\":[],\"isGenerated\":false},\"Tariff\":{\"dbName\":null,\"fields\":[{\"name\":\"id\",\"kind\":\"scalar\",\"isList\":false,\"isRequired\":true,\"isUnique\":false,\"isId\":true,\"isReadOnly\":false,\"hasDefaultValue\":true,\"type\":\"Int\",\"default\":{\"name\":\"autoincrement\",\"args\":[]},\"isGenerated\":false,\"isUpdatedAt\":false},{\"name\":\"providerId\",\"kind\":\"scalar\",\"isList\":false,\"isRequired\":true,\"isUnique\":false,\"isId\":false,\"isReadOnly\":true,\"hasDefaultValue\":false,\"type\":\"Int\",\"isGenerated\":false,\"isUpdatedAt\":false},{\"name\":\"provider\",\"kind\":\"object\",\"isList\":false,\"isRequired\":true,\"isUnique\":false,\"isId\":false,\"isReadOnly\":false,\"hasDefaultValue\":false,\"type\":\"Provider\",\"relationName\":\"ProviderToTariff\",\"relationFromFields\":[\"providerId\"],\"relationToFields\":[\"id\"],\"relationOnDelete\":\"Cascade\",\"isGenerated\":false,\"isUpdatedAt\":false},{\"name\":\"name\",\"kind\":\"scalar\",\"isList\":false,\"isRequired\":true,\"isUnique\":false,\"isId\":false,\"isReadOnly\":false,\"hasDefaultValue\":false,\"type\":\"String\",\"isGenerated\":false,\"isUpdatedAt\":false},{\"name\":\"isActive\",\"kind\":\"scalar\",\"isList\":false,\"isRequired\":true,\"isUnique\":false,\"isId\":false,\"isReadOnly\":false,\"hasDefaultValue\":true,\"type\":\"Boolean\",\"default\":true,\"isGenerated\":false,\"isUpdatedAt\":false},{\"name\":\"contracts\",\"kind\":\"object\",\"isList\":true,\"isRequired\":true,\"isUnique\":false,\"isId\":false,\"isReadOnly\":false,\"hasDefaultValue\":false,\"type\":\"Contract\",\"relationName\":\"ContractToTariff\",\"relationFromFields\":[],\"relationToFields\":[],\"isGenerated\":false,\"isUpdatedAt\":false},{\"name\":\"createdAt\",\"kind\":\"scalar\",\"isList\":false,\"isRequired\":true,\"isUnique\":false,\"isId\":false,\"isReadOnly\":false,\"hasDefaultValue\":true,\"type\":\"DateTime\",\"default\":{\"name\":\"now\",\"args\":[]},\"isGenerated\":false,\"isUpdatedAt\":false},{\"name\":\"updatedAt\",\"kind\":\"scalar\",\"isList\":false,\"isRequired\":true,\"isUnique\":false,\"isId\":false,\"isReadOnly\":false,\"hasDefaultValue\":false,\"type\":\"DateTime\",\"isGenerated\":false,\"isUpdatedAt\":true}],\"primaryKey\":null,\"uniqueFields\":[[\"providerId\",\"name\"]],\"uniqueIndexes\":[{\"name\":null,\"fields\":[\"providerId\",\"name\"]}],\"isGenerated\":false},\"ContractCategory\":{\"dbName\":null,\"fields\":[{\"name\":\"id\",\"kind\":\"scalar\",\"isList\":false,\"isRequired\":true,\"isUnique\":false,\"isId\":true,\"isReadOnly\":false,\"hasDefaultValue\":true,\"type\":\"Int\",\"default\":{\"name\":\"autoincrement\",\"args\":[]},\"isGenerated\":false,\"isUpdatedAt\":false},{\"name\":\"code\",\"kind\":\"scalar\",\"isList\":false,\"isRequired\":true,\"isUnique\":true,\"isId\":false,\"isReadOnly\":false,\"hasDefaultValue\":false,\"type\":\"String\",\"isGenerated\":false,\"isUpdatedAt\":false},{\"name\":\"name\",\"kind\":\"scalar\",\"isList\":false,\"isRequired\":true,\"isUnique\":false,\"isId\":false,\"isReadOnly\":false,\"hasDefaultValue\":false,\"type\":\"String\",\"isGenerated\":false,\"isUpdatedAt\":false},{\"name\":\"icon\",\"kind\":\"scalar\",\"isList\":false,\"isRequired\":false,\"isUnique\":false,\"isId\":false,\"isReadOnly\":false,\"hasDefaultValue\":false,\"type\":\"String\",\"isGenerated\":false,\"isUpdatedAt\":false},{\"name\":\"color\",\"kind\":\"scalar\",\"isList\":false,\"isRequired\":false,\"isUnique\":false,\"isId\":false,\"isReadOnly\":false,\"hasDefaultValue\":false,\"type\":\"String\",\"isGenerated\":false,\"isUpdatedAt\":false},{\"name\":\"sortOrder\",\"kind\":\"scalar\",\"isList\":false,\"isRequired\":true,\"isUnique\":false,\"isId\":false,\"isReadOnly\":false,\"hasDefaultValue\":true,\"type\":\"Int\",\"default\":0,\"isGenerated\":false,\"isUpdatedAt\":false},{\"name\":\"isActive\",\"kind\":\"scalar\",\"isList\":false,\"isRequired\":true,\"isUnique\":false,\"isId\":false,\"isReadOnly\":false,\"hasDefaultValue\":true,\"type\":\"Boolean\",\"default\":true,\"isGenerated\":false,\"isUpdatedAt\":false},{\"name\":\"contracts\",\"kind\":\"object\",\"isList\":true,\"isRequired\":true,\"isUnique\":false,\"isId\":false,\"isReadOnly\":false,\"hasDefaultValue\":false,\"type\":\"Contract\",\"relationName\":\"ContractToContractCategory\",\"relationFromFields\":[],\"relationToFields\":[],\"isGenerated\":false,\"isUpdatedAt\":false},{\"name\":\"createdAt\",\"kind\":\"scalar\",\"isList\":false,\"isRequired\":true,\"isUnique\":false,\"isId\":false,\"isReadOnly\":false,\"hasDefaultValue\":true,\"type\":\"DateTime\",\"default\":{\"name\":\"now\",\"args\":[]},\"isGenerated\":false,\"isUpdatedAt\":false},{\"name\":\"updatedAt\",\"kind\":\"scalar\",\"isList\":false,\"isRequired\":true,\"isUnique\":false,\"isId\":false,\"isReadOnly\":false,\"hasDefaultValue\":false,\"type\":\"DateTime\",\"isGenerated\":false,\"isUpdatedAt\":true}],\"primaryKey\":null,\"uniqueFields\":[],\"uniqueIndexes\":[],\"isGenerated\":false},\"Contract\":{\"dbName\":null,\"fields\":[{\"name\":\"id\",\"kind\":\"scalar\",\"isList\":false,\"isRequired\":true,\"isUnique\":false,\"isId\":true,\"isReadOnly\":false,\"hasDefaultValue\":true,\"type\":\"Int\",\"default\":{\"name\":\"autoincrement\",\"args\":[]},\"isGenerated\":false,\"isUpdatedAt\":false},{\"name\":\"contractNumber\",\"kind\":\"scalar\",\"isList\":false,\"isRequired\":true,\"isUnique\":true,\"isId\":false,\"isReadOnly\":false,\"hasDefaultValue\":false,\"type\":\"String\",\"isGenerated\":false,\"isUpdatedAt\":false},{\"name\":\"customerId\",\"kind\":\"scalar\",\"isList\":false,\"isRequired\":true,\"isUnique\":false,\"isId\":false,\"isReadOnly\":true,\"hasDefaultValue\":false,\"type\":\"Int\",\"isGenerated\":false,\"isUpdatedAt\":false},{\"name\":\"customer\",\"kind\":\"object\",\"isList\":false,\"isRequired\":true,\"isUnique\":false,\"isId\":false,\"isReadOnly\":false,\"hasDefaultValue\":false,\"type\":\"Customer\",\"relationName\":\"ContractToCustomer\",\"relationFromFields\":[\"customerId\"],\"relationToFields\":[\"id\"],\"relationOnDelete\":\"Cascade\",\"isGenerated\":false,\"isUpdatedAt\":false},{\"name\":\"type\",\"kind\":\"enum\",\"isList\":false,\"isRequired\":true,\"isUnique\":false,\"isId\":false,\"isReadOnly\":false,\"hasDefaultValue\":false,\"type\":\"ContractType\",\"isGenerated\":false,\"isUpdatedAt\":false},{\"name\":\"status\",\"kind\":\"enum\",\"isList\":false,\"isRequired\":true,\"isUnique\":false,\"isId\":false,\"isReadOnly\":false,\"hasDefaultValue\":true,\"type\":\"ContractStatus\",\"default\":\"DRAFT\",\"isGenerated\":false,\"isUpdatedAt\":false},{\"name\":\"contractCategoryId\",\"kind\":\"scalar\",\"isList\":false,\"isRequired\":false,\"isUnique\":false,\"isId\":false,\"isReadOnly\":true,\"hasDefaultValue\":false,\"type\":\"Int\",\"isGenerated\":false,\"isUpdatedAt\":false},{\"name\":\"contractCategory\",\"kind\":\"object\",\"isList\":false,\"isRequired\":false,\"isUnique\":false,\"isId\":false,\"isReadOnly\":false,\"hasDefaultValue\":false,\"type\":\"ContractCategory\",\"relationName\":\"ContractToContractCategory\",\"relationFromFields\":[\"contractCategoryId\"],\"relationToFields\":[\"id\"],\"isGenerated\":false,\"isUpdatedAt\":false},{\"name\":\"addressId\",\"kind\":\"scalar\",\"isList\":false,\"isRequired\":false,\"isUnique\":false,\"isId\":false,\"isReadOnly\":true,\"hasDefaultValue\":false,\"type\":\"Int\",\"isGenerated\":false,\"isUpdatedAt\":false},{\"name\":\"address\",\"kind\":\"object\",\"isList\":false,\"isRequired\":false,\"isUnique\":false,\"isId\":false,\"isReadOnly\":false,\"hasDefaultValue\":false,\"type\":\"Address\",\"relationName\":\"AddressToContract\",\"relationFromFields\":[\"addressId\"],\"relationToFields\":[\"id\"],\"isGenerated\":false,\"isUpdatedAt\":false},{\"name\":\"bankCardId\",\"kind\":\"scalar\",\"isList\":false,\"isRequired\":false,\"isUnique\":false,\"isId\":false,\"isReadOnly\":true,\"hasDefaultValue\":false,\"type\":\"Int\",\"isGenerated\":false,\"isUpdatedAt\":false},{\"name\":\"bankCard\",\"kind\":\"object\",\"isList\":false,\"isRequired\":false,\"isUnique\":false,\"isId\":false,\"isReadOnly\":false,\"hasDefaultValue\":false,\"type\":\"BankCard\",\"relationName\":\"BankCardToContract\",\"relationFromFields\":[\"bankCardId\"],\"relationToFields\":[\"id\"],\"isGenerated\":false,\"isUpdatedAt\":false},{\"name\":\"identityDocumentId\",\"kind\":\"scalar\",\"isList\":false,\"isRequired\":false,\"isUnique\":false,\"isId\":false,\"isReadOnly\":true,\"hasDefaultValue\":false,\"type\":\"Int\",\"isGenerated\":false,\"isUpdatedAt\":false},{\"name\":\"identityDocument\",\"kind\":\"object\",\"isList\":false,\"isRequired\":false,\"isUnique\":false,\"isId\":false,\"isReadOnly\":false,\"hasDefaultValue\":false,\"type\":\"IdentityDocument\",\"relationName\":\"ContractToIdentityDocument\",\"relationFromFields\":[\"identityDocumentId\"],\"relationToFields\":[\"id\"],\"isGenerated\":false,\"isUpdatedAt\":false},{\"name\":\"salesPlatformId\",\"kind\":\"scalar\",\"isList\":false,\"isRequired\":false,\"isUnique\":false,\"isId\":false,\"isReadOnly\":true,\"hasDefaultValue\":false,\"type\":\"Int\",\"isGenerated\":false,\"isUpdatedAt\":false},{\"name\":\"salesPlatform\",\"kind\":\"object\",\"isList\":false,\"isRequired\":false,\"isUnique\":false,\"isId\":false,\"isReadOnly\":false,\"hasDefaultValue\":false,\"type\":\"SalesPlatform\",\"relationName\":\"ContractToSalesPlatform\",\"relationFromFields\":[\"salesPlatformId\"],\"relationToFields\":[\"id\"],\"isGenerated\":false,\"isUpdatedAt\":false},{\"name\":\"cancellationPeriodId\",\"kind\":\"scalar\",\"isList\":false,\"isRequired\":false,\"isUnique\":false,\"isId\":false,\"isReadOnly\":true,\"hasDefaultValue\":false,\"type\":\"Int\",\"isGenerated\":false,\"isUpdatedAt\":false},{\"name\":\"cancellationPeriod\",\"kind\":\"object\",\"isList\":false,\"isRequired\":false,\"isUnique\":false,\"isId\":false,\"isReadOnly\":false,\"hasDefaultValue\":false,\"type\":\"CancellationPeriod\",\"relationName\":\"CancellationPeriodToContract\",\"relationFromFields\":[\"cancellationPeriodId\"],\"relationToFields\":[\"id\"],\"isGenerated\":false,\"isUpdatedAt\":false},{\"name\":\"contractDurationId\",\"kind\":\"scalar\",\"isList\":false,\"isRequired\":false,\"isUnique\":false,\"isId\":false,\"isReadOnly\":true,\"hasDefaultValue\":false,\"type\":\"Int\",\"isGenerated\":false,\"isUpdatedAt\":false},{\"name\":\"contractDuration\",\"kind\":\"object\",\"isList\":false,\"isRequired\":false,\"isUnique\":false,\"isId\":false,\"isReadOnly\":false,\"hasDefaultValue\":false,\"type\":\"ContractDuration\",\"relationName\":\"ContractToContractDuration\",\"relationFromFields\":[\"contractDurationId\"],\"relationToFields\":[\"id\"],\"isGenerated\":false,\"isUpdatedAt\":false},{\"name\":\"previousContractId\",\"kind\":\"scalar\",\"isList\":false,\"isRequired\":false,\"isUnique\":true,\"isId\":false,\"isReadOnly\":true,\"hasDefaultValue\":false,\"type\":\"Int\",\"isGenerated\":false,\"isUpdatedAt\":false},{\"name\":\"previousContract\",\"kind\":\"object\",\"isList\":false,\"isRequired\":false,\"isUnique\":false,\"isId\":false,\"isReadOnly\":false,\"hasDefaultValue\":false,\"type\":\"Contract\",\"relationName\":\"ContractHistory\",\"relationFromFields\":[\"previousContractId\"],\"relationToFields\":[\"id\"],\"isGenerated\":false,\"isUpdatedAt\":false},{\"name\":\"followUpContract\",\"kind\":\"object\",\"isList\":false,\"isRequired\":false,\"isUnique\":false,\"isId\":false,\"isReadOnly\":false,\"hasDefaultValue\":false,\"type\":\"Contract\",\"relationName\":\"ContractHistory\",\"relationFromFields\":[],\"relationToFields\":[],\"isGenerated\":false,\"isUpdatedAt\":false},{\"name\":\"providerId\",\"kind\":\"scalar\",\"isList\":false,\"isRequired\":false,\"isUnique\":false,\"isId\":false,\"isReadOnly\":true,\"hasDefaultValue\":false,\"type\":\"Int\",\"isGenerated\":false,\"isUpdatedAt\":false},{\"name\":\"provider\",\"kind\":\"object\",\"isList\":false,\"isRequired\":false,\"isUnique\":false,\"isId\":false,\"isReadOnly\":false,\"hasDefaultValue\":false,\"type\":\"Provider\",\"relationName\":\"ContractToProvider\",\"relationFromFields\":[\"providerId\"],\"relationToFields\":[\"id\"],\"isGenerated\":false,\"isUpdatedAt\":false},{\"name\":\"tariffId\",\"kind\":\"scalar\",\"isList\":false,\"isRequired\":false,\"isUnique\":false,\"isId\":false,\"isReadOnly\":true,\"hasDefaultValue\":false,\"type\":\"Int\",\"isGenerated\":false,\"isUpdatedAt\":false},{\"name\":\"tariff\",\"kind\":\"object\",\"isList\":false,\"isRequired\":false,\"isUnique\":false,\"isId\":false,\"isReadOnly\":false,\"hasDefaultValue\":false,\"type\":\"Tariff\",\"relationName\":\"ContractToTariff\",\"relationFromFields\":[\"tariffId\"],\"relationToFields\":[\"id\"],\"isGenerated\":false,\"isUpdatedAt\":false},{\"name\":\"providerName\",\"kind\":\"scalar\",\"isList\":false,\"isRequired\":false,\"isUnique\":false,\"isId\":false,\"isReadOnly\":false,\"hasDefaultValue\":false,\"type\":\"String\",\"isGenerated\":false,\"isUpdatedAt\":false},{\"name\":\"tariffName\",\"kind\":\"scalar\",\"isList\":false,\"isRequired\":false,\"isUnique\":false,\"isId\":false,\"isReadOnly\":false,\"hasDefaultValue\":false,\"type\":\"String\",\"isGenerated\":false,\"isUpdatedAt\":false},{\"name\":\"customerNumberAtProvider\",\"kind\":\"scalar\",\"isList\":false,\"isRequired\":false,\"isUnique\":false,\"isId\":false,\"isReadOnly\":false,\"hasDefaultValue\":false,\"type\":\"String\",\"isGenerated\":false,\"isUpdatedAt\":false},{\"name\":\"priceFirst12Months\",\"kind\":\"scalar\",\"isList\":false,\"isRequired\":false,\"isUnique\":false,\"isId\":false,\"isReadOnly\":false,\"hasDefaultValue\":false,\"type\":\"String\",\"isGenerated\":false,\"isUpdatedAt\":false},{\"name\":\"priceFrom13Months\",\"kind\":\"scalar\",\"isList\":false,\"isRequired\":false,\"isUnique\":false,\"isId\":false,\"isReadOnly\":false,\"hasDefaultValue\":false,\"type\":\"String\",\"isGenerated\":false,\"isUpdatedAt\":false},{\"name\":\"priceAfter24Months\",\"kind\":\"scalar\",\"isList\":false,\"isRequired\":false,\"isUnique\":false,\"isId\":false,\"isReadOnly\":false,\"hasDefaultValue\":false,\"type\":\"String\",\"isGenerated\":false,\"isUpdatedAt\":false},{\"name\":\"startDate\",\"kind\":\"scalar\",\"isList\":false,\"isRequired\":false,\"isUnique\":false,\"isId\":false,\"isReadOnly\":false,\"hasDefaultValue\":false,\"type\":\"DateTime\",\"isGenerated\":false,\"isUpdatedAt\":false},{\"name\":\"endDate\",\"kind\":\"scalar\",\"isList\":false,\"isRequired\":false,\"isUnique\":false,\"isId\":false,\"isReadOnly\":false,\"hasDefaultValue\":false,\"type\":\"DateTime\",\"isGenerated\":false,\"isUpdatedAt\":false},{\"name\":\"commission\",\"kind\":\"scalar\",\"isList\":false,\"isRequired\":false,\"isUnique\":false,\"isId\":false,\"isReadOnly\":false,\"hasDefaultValue\":false,\"type\":\"Float\",\"isGenerated\":false,\"isUpdatedAt\":false},{\"name\":\"cancellationLetterPath\",\"kind\":\"scalar\",\"isList\":false,\"isRequired\":false,\"isUnique\":false,\"isId\":false,\"isReadOnly\":false,\"hasDefaultValue\":false,\"type\":\"String\",\"isGenerated\":false,\"isUpdatedAt\":false},{\"name\":\"cancellationConfirmationPath\",\"kind\":\"scalar\",\"isList\":false,\"isRequired\":false,\"isUnique\":false,\"isId\":false,\"isReadOnly\":false,\"hasDefaultValue\":false,\"type\":\"String\",\"isGenerated\":false,\"isUpdatedAt\":false},{\"name\":\"cancellationLetterOptionsPath\",\"kind\":\"scalar\",\"isList\":false,\"isRequired\":false,\"isUnique\":false,\"isId\":false,\"isReadOnly\":false,\"hasDefaultValue\":false,\"type\":\"String\",\"isGenerated\":false,\"isUpdatedAt\":false},{\"name\":\"cancellationConfirmationOptionsPath\",\"kind\":\"scalar\",\"isList\":false,\"isRequired\":false,\"isUnique\":false,\"isId\":false,\"isReadOnly\":false,\"hasDefaultValue\":false,\"type\":\"String\",\"isGenerated\":false,\"isUpdatedAt\":false},{\"name\":\"cancellationConfirmationDate\",\"kind\":\"scalar\",\"isList\":false,\"isRequired\":false,\"isUnique\":false,\"isId\":false,\"isReadOnly\":false,\"hasDefaultValue\":false,\"type\":\"DateTime\",\"isGenerated\":false,\"isUpdatedAt\":false},{\"name\":\"cancellationConfirmationOptionsDate\",\"kind\":\"scalar\",\"isList\":false,\"isRequired\":false,\"isUnique\":false,\"isId\":false,\"isReadOnly\":false,\"hasDefaultValue\":false,\"type\":\"DateTime\",\"isGenerated\":false,\"isUpdatedAt\":false},{\"name\":\"wasSpecialCancellation\",\"kind\":\"scalar\",\"isList\":false,\"isRequired\":true,\"isUnique\":false,\"isId\":false,\"isReadOnly\":false,\"hasDefaultValue\":true,\"type\":\"Boolean\",\"default\":false,\"isGenerated\":false,\"isUpdatedAt\":false},{\"name\":\"portalUsername\",\"kind\":\"scalar\",\"isList\":false,\"isRequired\":false,\"isUnique\":false,\"isId\":false,\"isReadOnly\":false,\"hasDefaultValue\":false,\"type\":\"String\",\"isGenerated\":false,\"isUpdatedAt\":false},{\"name\":\"portalPasswordEncrypted\",\"kind\":\"scalar\",\"isList\":false,\"isRequired\":false,\"isUnique\":false,\"isId\":false,\"isReadOnly\":false,\"hasDefaultValue\":false,\"type\":\"String\",\"isGenerated\":false,\"isUpdatedAt\":false},{\"name\":\"stressfreiEmailId\",\"kind\":\"scalar\",\"isList\":false,\"isRequired\":false,\"isUnique\":false,\"isId\":false,\"isReadOnly\":true,\"hasDefaultValue\":false,\"type\":\"Int\",\"isGenerated\":false,\"isUpdatedAt\":false},{\"name\":\"stressfreiEmail\",\"kind\":\"object\",\"isList\":false,\"isRequired\":false,\"isUnique\":false,\"isId\":false,\"isReadOnly\":false,\"hasDefaultValue\":false,\"type\":\"StressfreiEmail\",\"relationName\":\"ContractToStressfreiEmail\",\"relationFromFields\":[\"stressfreiEmailId\"],\"relationToFields\":[\"id\"],\"isGenerated\":false,\"isUpdatedAt\":false},{\"name\":\"notes\",\"kind\":\"scalar\",\"isList\":false,\"isRequired\":false,\"isUnique\":false,\"isId\":false,\"isReadOnly\":false,\"hasDefaultValue\":false,\"type\":\"String\",\"isGenerated\":false,\"isUpdatedAt\":false},{\"name\":\"energyDetails\",\"kind\":\"object\",\"isList\":false,\"isRequired\":false,\"isUnique\":false,\"isId\":false,\"isReadOnly\":false,\"hasDefaultValue\":false,\"type\":\"EnergyContractDetails\",\"relationName\":\"ContractToEnergyContractDetails\",\"relationFromFields\":[],\"relationToFields\":[],\"isGenerated\":false,\"isUpdatedAt\":false},{\"name\":\"internetDetails\",\"kind\":\"object\",\"isList\":false,\"isRequired\":false,\"isUnique\":false,\"isId\":false,\"isReadOnly\":false,\"hasDefaultValue\":false,\"type\":\"InternetContractDetails\",\"relationName\":\"ContractToInternetContractDetails\",\"relationFromFields\":[],\"relationToFields\":[],\"isGenerated\":false,\"isUpdatedAt\":false},{\"name\":\"mobileDetails\",\"kind\":\"object\",\"isList\":false,\"isRequired\":false,\"isUnique\":false,\"isId\":false,\"isReadOnly\":false,\"hasDefaultValue\":false,\"type\":\"MobileContractDetails\",\"relationName\":\"ContractToMobileContractDetails\",\"relationFromFields\":[],\"relationToFields\":[],\"isGenerated\":false,\"isUpdatedAt\":false},{\"name\":\"tvDetails\",\"kind\":\"object\",\"isList\":false,\"isRequired\":false,\"isUnique\":false,\"isId\":false,\"isReadOnly\":false,\"hasDefaultValue\":false,\"type\":\"TvContractDetails\",\"relationName\":\"ContractToTvContractDetails\",\"relationFromFields\":[],\"relationToFields\":[],\"isGenerated\":false,\"isUpdatedAt\":false},{\"name\":\"carInsuranceDetails\",\"kind\":\"object\",\"isList\":false,\"isRequired\":false,\"isUnique\":false,\"isId\":false,\"isReadOnly\":false,\"hasDefaultValue\":false,\"type\":\"CarInsuranceDetails\",\"relationName\":\"CarInsuranceDetailsToContract\",\"relationFromFields\":[],\"relationToFields\":[],\"isGenerated\":false,\"isUpdatedAt\":false},{\"name\":\"tasks\",\"kind\":\"object\",\"isList\":true,\"isRequired\":true,\"isUnique\":false,\"isId\":false,\"isReadOnly\":false,\"hasDefaultValue\":false,\"type\":\"ContractTask\",\"relationName\":\"ContractToContractTask\",\"relationFromFields\":[],\"relationToFields\":[],\"isGenerated\":false,\"isUpdatedAt\":false},{\"name\":\"createdAt\",\"kind\":\"scalar\",\"isList\":false,\"isRequired\":true,\"isUnique\":false,\"isId\":false,\"isReadOnly\":false,\"hasDefaultValue\":true,\"type\":\"DateTime\",\"default\":{\"name\":\"now\",\"args\":[]},\"isGenerated\":false,\"isUpdatedAt\":false},{\"name\":\"updatedAt\",\"kind\":\"scalar\",\"isList\":false,\"isRequired\":true,\"isUnique\":false,\"isId\":false,\"isReadOnly\":false,\"hasDefaultValue\":false,\"type\":\"DateTime\",\"isGenerated\":false,\"isUpdatedAt\":true}],\"primaryKey\":null,\"uniqueFields\":[],\"uniqueIndexes\":[],\"isGenerated\":false},\"ContractTask\":{\"dbName\":null,\"fields\":[{\"name\":\"id\",\"kind\":\"scalar\",\"isList\":false,\"isRequired\":true,\"isUnique\":false,\"isId\":true,\"isReadOnly\":false,\"hasDefaultValue\":true,\"type\":\"Int\",\"default\":{\"name\":\"autoincrement\",\"args\":[]},\"isGenerated\":false,\"isUpdatedAt\":false},{\"name\":\"contractId\",\"kind\":\"scalar\",\"isList\":false,\"isRequired\":true,\"isUnique\":false,\"isId\":false,\"isReadOnly\":true,\"hasDefaultValue\":false,\"type\":\"Int\",\"isGenerated\":false,\"isUpdatedAt\":false},{\"name\":\"contract\",\"kind\":\"object\",\"isList\":false,\"isRequired\":true,\"isUnique\":false,\"isId\":false,\"isReadOnly\":false,\"hasDefaultValue\":false,\"type\":\"Contract\",\"relationName\":\"ContractToContractTask\",\"relationFromFields\":[\"contractId\"],\"relationToFields\":[\"id\"],\"relationOnDelete\":\"Cascade\",\"isGenerated\":false,\"isUpdatedAt\":false},{\"name\":\"title\",\"kind\":\"scalar\",\"isList\":false,\"isRequired\":true,\"isUnique\":false,\"isId\":false,\"isReadOnly\":false,\"hasDefaultValue\":false,\"type\":\"String\",\"isGenerated\":false,\"isUpdatedAt\":false},{\"name\":\"description\",\"kind\":\"scalar\",\"isList\":false,\"isRequired\":false,\"isUnique\":false,\"isId\":false,\"isReadOnly\":false,\"hasDefaultValue\":false,\"type\":\"String\",\"isGenerated\":false,\"isUpdatedAt\":false},{\"name\":\"status\",\"kind\":\"enum\",\"isList\":false,\"isRequired\":true,\"isUnique\":false,\"isId\":false,\"isReadOnly\":false,\"hasDefaultValue\":true,\"type\":\"ContractTaskStatus\",\"default\":\"OPEN\",\"isGenerated\":false,\"isUpdatedAt\":false},{\"name\":\"visibleInPortal\",\"kind\":\"scalar\",\"isList\":false,\"isRequired\":true,\"isUnique\":false,\"isId\":false,\"isReadOnly\":false,\"hasDefaultValue\":true,\"type\":\"Boolean\",\"default\":false,\"isGenerated\":false,\"isUpdatedAt\":false},{\"name\":\"createdBy\",\"kind\":\"scalar\",\"isList\":false,\"isRequired\":false,\"isUnique\":false,\"isId\":false,\"isReadOnly\":false,\"hasDefaultValue\":false,\"type\":\"String\",\"isGenerated\":false,\"isUpdatedAt\":false},{\"name\":\"completedAt\",\"kind\":\"scalar\",\"isList\":false,\"isRequired\":false,\"isUnique\":false,\"isId\":false,\"isReadOnly\":false,\"hasDefaultValue\":false,\"type\":\"DateTime\",\"isGenerated\":false,\"isUpdatedAt\":false},{\"name\":\"subtasks\",\"kind\":\"object\",\"isList\":true,\"isRequired\":true,\"isUnique\":false,\"isId\":false,\"isReadOnly\":false,\"hasDefaultValue\":false,\"type\":\"ContractTaskSubtask\",\"relationName\":\"ContractTaskToContractTaskSubtask\",\"relationFromFields\":[],\"relationToFields\":[],\"isGenerated\":false,\"isUpdatedAt\":false},{\"name\":\"createdAt\",\"kind\":\"scalar\",\"isList\":false,\"isRequired\":true,\"isUnique\":false,\"isId\":false,\"isReadOnly\":false,\"hasDefaultValue\":true,\"type\":\"DateTime\",\"default\":{\"name\":\"now\",\"args\":[]},\"isGenerated\":false,\"isUpdatedAt\":false},{\"name\":\"updatedAt\",\"kind\":\"scalar\",\"isList\":false,\"isRequired\":true,\"isUnique\":false,\"isId\":false,\"isReadOnly\":false,\"hasDefaultValue\":false,\"type\":\"DateTime\",\"isGenerated\":false,\"isUpdatedAt\":true}],\"primaryKey\":null,\"uniqueFields\":[],\"uniqueIndexes\":[],\"isGenerated\":false},\"ContractTaskSubtask\":{\"dbName\":null,\"fields\":[{\"name\":\"id\",\"kind\":\"scalar\",\"isList\":false,\"isRequired\":true,\"isUnique\":false,\"isId\":true,\"isReadOnly\":false,\"hasDefaultValue\":true,\"type\":\"Int\",\"default\":{\"name\":\"autoincrement\",\"args\":[]},\"isGenerated\":false,\"isUpdatedAt\":false},{\"name\":\"taskId\",\"kind\":\"scalar\",\"isList\":false,\"isRequired\":true,\"isUnique\":false,\"isId\":false,\"isReadOnly\":true,\"hasDefaultValue\":false,\"type\":\"Int\",\"isGenerated\":false,\"isUpdatedAt\":false},{\"name\":\"task\",\"kind\":\"object\",\"isList\":false,\"isRequired\":true,\"isUnique\":false,\"isId\":false,\"isReadOnly\":false,\"hasDefaultValue\":false,\"type\":\"ContractTask\",\"relationName\":\"ContractTaskToContractTaskSubtask\",\"relationFromFields\":[\"taskId\"],\"relationToFields\":[\"id\"],\"relationOnDelete\":\"Cascade\",\"isGenerated\":false,\"isUpdatedAt\":false},{\"name\":\"title\",\"kind\":\"scalar\",\"isList\":false,\"isRequired\":true,\"isUnique\":false,\"isId\":false,\"isReadOnly\":false,\"hasDefaultValue\":false,\"type\":\"String\",\"isGenerated\":false,\"isUpdatedAt\":false},{\"name\":\"status\",\"kind\":\"enum\",\"isList\":false,\"isRequired\":true,\"isUnique\":false,\"isId\":false,\"isReadOnly\":false,\"hasDefaultValue\":true,\"type\":\"ContractTaskStatus\",\"default\":\"OPEN\",\"isGenerated\":false,\"isUpdatedAt\":false},{\"name\":\"createdBy\",\"kind\":\"scalar\",\"isList\":false,\"isRequired\":false,\"isUnique\":false,\"isId\":false,\"isReadOnly\":false,\"hasDefaultValue\":false,\"type\":\"String\",\"isGenerated\":false,\"isUpdatedAt\":false},{\"name\":\"completedAt\",\"kind\":\"scalar\",\"isList\":false,\"isRequired\":false,\"isUnique\":false,\"isId\":false,\"isReadOnly\":false,\"hasDefaultValue\":false,\"type\":\"DateTime\",\"isGenerated\":false,\"isUpdatedAt\":false},{\"name\":\"createdAt\",\"kind\":\"scalar\",\"isList\":false,\"isRequired\":true,\"isUnique\":false,\"isId\":false,\"isReadOnly\":false,\"hasDefaultValue\":true,\"type\":\"DateTime\",\"default\":{\"name\":\"now\",\"args\":[]},\"isGenerated\":false,\"isUpdatedAt\":false},{\"name\":\"updatedAt\",\"kind\":\"scalar\",\"isList\":false,\"isRequired\":true,\"isUnique\":false,\"isId\":false,\"isReadOnly\":false,\"hasDefaultValue\":false,\"type\":\"DateTime\",\"isGenerated\":false,\"isUpdatedAt\":true}],\"primaryKey\":null,\"uniqueFields\":[],\"uniqueIndexes\":[],\"isGenerated\":false},\"EnergyContractDetails\":{\"dbName\":null,\"fields\":[{\"name\":\"id\",\"kind\":\"scalar\",\"isList\":false,\"isRequired\":true,\"isUnique\":false,\"isId\":true,\"isReadOnly\":false,\"hasDefaultValue\":true,\"type\":\"Int\",\"default\":{\"name\":\"autoincrement\",\"args\":[]},\"isGenerated\":false,\"isUpdatedAt\":false},{\"name\":\"contractId\",\"kind\":\"scalar\",\"isList\":false,\"isRequired\":true,\"isUnique\":true,\"isId\":false,\"isReadOnly\":true,\"hasDefaultValue\":false,\"type\":\"Int\",\"isGenerated\":false,\"isUpdatedAt\":false},{\"name\":\"contract\",\"kind\":\"object\",\"isList\":false,\"isRequired\":true,\"isUnique\":false,\"isId\":false,\"isReadOnly\":false,\"hasDefaultValue\":false,\"type\":\"Contract\",\"relationName\":\"ContractToEnergyContractDetails\",\"relationFromFields\":[\"contractId\"],\"relationToFields\":[\"id\"],\"relationOnDelete\":\"Cascade\",\"isGenerated\":false,\"isUpdatedAt\":false},{\"name\":\"meterId\",\"kind\":\"scalar\",\"isList\":false,\"isRequired\":false,\"isUnique\":false,\"isId\":false,\"isReadOnly\":true,\"hasDefaultValue\":false,\"type\":\"Int\",\"isGenerated\":false,\"isUpdatedAt\":false},{\"name\":\"meter\",\"kind\":\"object\",\"isList\":false,\"isRequired\":false,\"isUnique\":false,\"isId\":false,\"isReadOnly\":false,\"hasDefaultValue\":false,\"type\":\"Meter\",\"relationName\":\"EnergyContractDetailsToMeter\",\"relationFromFields\":[\"meterId\"],\"relationToFields\":[\"id\"],\"isGenerated\":false,\"isUpdatedAt\":false},{\"name\":\"annualConsumption\",\"kind\":\"scalar\",\"isList\":false,\"isRequired\":false,\"isUnique\":false,\"isId\":false,\"isReadOnly\":false,\"hasDefaultValue\":false,\"type\":\"Float\",\"isGenerated\":false,\"isUpdatedAt\":false},{\"name\":\"basePrice\",\"kind\":\"scalar\",\"isList\":false,\"isRequired\":false,\"isUnique\":false,\"isId\":false,\"isReadOnly\":false,\"hasDefaultValue\":false,\"type\":\"Float\",\"isGenerated\":false,\"isUpdatedAt\":false},{\"name\":\"unitPrice\",\"kind\":\"scalar\",\"isList\":false,\"isRequired\":false,\"isUnique\":false,\"isId\":false,\"isReadOnly\":false,\"hasDefaultValue\":false,\"type\":\"Float\",\"isGenerated\":false,\"isUpdatedAt\":false},{\"name\":\"bonus\",\"kind\":\"scalar\",\"isList\":false,\"isRequired\":false,\"isUnique\":false,\"isId\":false,\"isReadOnly\":false,\"hasDefaultValue\":false,\"type\":\"Float\",\"isGenerated\":false,\"isUpdatedAt\":false},{\"name\":\"previousProviderName\",\"kind\":\"scalar\",\"isList\":false,\"isRequired\":false,\"isUnique\":false,\"isId\":false,\"isReadOnly\":false,\"hasDefaultValue\":false,\"type\":\"String\",\"isGenerated\":false,\"isUpdatedAt\":false},{\"name\":\"previousCustomerNumber\",\"kind\":\"scalar\",\"isList\":false,\"isRequired\":false,\"isUnique\":false,\"isId\":false,\"isReadOnly\":false,\"hasDefaultValue\":false,\"type\":\"String\",\"isGenerated\":false,\"isUpdatedAt\":false}],\"primaryKey\":null,\"uniqueFields\":[],\"uniqueIndexes\":[],\"isGenerated\":false},\"InternetContractDetails\":{\"dbName\":null,\"fields\":[{\"name\":\"id\",\"kind\":\"scalar\",\"isList\":false,\"isRequired\":true,\"isUnique\":false,\"isId\":true,\"isReadOnly\":false,\"hasDefaultValue\":true,\"type\":\"Int\",\"default\":{\"name\":\"autoincrement\",\"args\":[]},\"isGenerated\":false,\"isUpdatedAt\":false},{\"name\":\"contractId\",\"kind\":\"scalar\",\"isList\":false,\"isRequired\":true,\"isUnique\":true,\"isId\":false,\"isReadOnly\":true,\"hasDefaultValue\":false,\"type\":\"Int\",\"isGenerated\":false,\"isUpdatedAt\":false},{\"name\":\"contract\",\"kind\":\"object\",\"isList\":false,\"isRequired\":true,\"isUnique\":false,\"isId\":false,\"isReadOnly\":false,\"hasDefaultValue\":false,\"type\":\"Contract\",\"relationName\":\"ContractToInternetContractDetails\",\"relationFromFields\":[\"contractId\"],\"relationToFields\":[\"id\"],\"relationOnDelete\":\"Cascade\",\"isGenerated\":false,\"isUpdatedAt\":false},{\"name\":\"downloadSpeed\",\"kind\":\"scalar\",\"isList\":false,\"isRequired\":false,\"isUnique\":false,\"isId\":false,\"isReadOnly\":false,\"hasDefaultValue\":false,\"type\":\"Int\",\"isGenerated\":false,\"isUpdatedAt\":false},{\"name\":\"uploadSpeed\",\"kind\":\"scalar\",\"isList\":false,\"isRequired\":false,\"isUnique\":false,\"isId\":false,\"isReadOnly\":false,\"hasDefaultValue\":false,\"type\":\"Int\",\"isGenerated\":false,\"isUpdatedAt\":false},{\"name\":\"routerModel\",\"kind\":\"scalar\",\"isList\":false,\"isRequired\":false,\"isUnique\":false,\"isId\":false,\"isReadOnly\":false,\"hasDefaultValue\":false,\"type\":\"String\",\"isGenerated\":false,\"isUpdatedAt\":false},{\"name\":\"routerSerialNumber\",\"kind\":\"scalar\",\"isList\":false,\"isRequired\":false,\"isUnique\":false,\"isId\":false,\"isReadOnly\":false,\"hasDefaultValue\":false,\"type\":\"String\",\"isGenerated\":false,\"isUpdatedAt\":false},{\"name\":\"installationDate\",\"kind\":\"scalar\",\"isList\":false,\"isRequired\":false,\"isUnique\":false,\"isId\":false,\"isReadOnly\":false,\"hasDefaultValue\":false,\"type\":\"DateTime\",\"isGenerated\":false,\"isUpdatedAt\":false},{\"name\":\"internetUsername\",\"kind\":\"scalar\",\"isList\":false,\"isRequired\":false,\"isUnique\":false,\"isId\":false,\"isReadOnly\":false,\"hasDefaultValue\":false,\"type\":\"String\",\"isGenerated\":false,\"isUpdatedAt\":false},{\"name\":\"internetPasswordEncrypted\",\"kind\":\"scalar\",\"isList\":false,\"isRequired\":false,\"isUnique\":false,\"isId\":false,\"isReadOnly\":false,\"hasDefaultValue\":false,\"type\":\"String\",\"isGenerated\":false,\"isUpdatedAt\":false},{\"name\":\"homeId\",\"kind\":\"scalar\",\"isList\":false,\"isRequired\":false,\"isUnique\":false,\"isId\":false,\"isReadOnly\":false,\"hasDefaultValue\":false,\"type\":\"String\",\"isGenerated\":false,\"isUpdatedAt\":false},{\"name\":\"activationCode\",\"kind\":\"scalar\",\"isList\":false,\"isRequired\":false,\"isUnique\":false,\"isId\":false,\"isReadOnly\":false,\"hasDefaultValue\":false,\"type\":\"String\",\"isGenerated\":false,\"isUpdatedAt\":false},{\"name\":\"phoneNumbers\",\"kind\":\"object\",\"isList\":true,\"isRequired\":true,\"isUnique\":false,\"isId\":false,\"isReadOnly\":false,\"hasDefaultValue\":false,\"type\":\"PhoneNumber\",\"relationName\":\"InternetContractDetailsToPhoneNumber\",\"relationFromFields\":[],\"relationToFields\":[],\"isGenerated\":false,\"isUpdatedAt\":false}],\"primaryKey\":null,\"uniqueFields\":[],\"uniqueIndexes\":[],\"isGenerated\":false},\"PhoneNumber\":{\"dbName\":null,\"fields\":[{\"name\":\"id\",\"kind\":\"scalar\",\"isList\":false,\"isRequired\":true,\"isUnique\":false,\"isId\":true,\"isReadOnly\":false,\"hasDefaultValue\":true,\"type\":\"Int\",\"default\":{\"name\":\"autoincrement\",\"args\":[]},\"isGenerated\":false,\"isUpdatedAt\":false},{\"name\":\"internetContractDetailsId\",\"kind\":\"scalar\",\"isList\":false,\"isRequired\":true,\"isUnique\":false,\"isId\":false,\"isReadOnly\":true,\"hasDefaultValue\":false,\"type\":\"Int\",\"isGenerated\":false,\"isUpdatedAt\":false},{\"name\":\"internetDetails\",\"kind\":\"object\",\"isList\":false,\"isRequired\":true,\"isUnique\":false,\"isId\":false,\"isReadOnly\":false,\"hasDefaultValue\":false,\"type\":\"InternetContractDetails\",\"relationName\":\"InternetContractDetailsToPhoneNumber\",\"relationFromFields\":[\"internetContractDetailsId\"],\"relationToFields\":[\"id\"],\"relationOnDelete\":\"Cascade\",\"isGenerated\":false,\"isUpdatedAt\":false},{\"name\":\"phoneNumber\",\"kind\":\"scalar\",\"isList\":false,\"isRequired\":true,\"isUnique\":false,\"isId\":false,\"isReadOnly\":false,\"hasDefaultValue\":false,\"type\":\"String\",\"isGenerated\":false,\"isUpdatedAt\":false},{\"name\":\"isMain\",\"kind\":\"scalar\",\"isList\":false,\"isRequired\":true,\"isUnique\":false,\"isId\":false,\"isReadOnly\":false,\"hasDefaultValue\":true,\"type\":\"Boolean\",\"default\":false,\"isGenerated\":false,\"isUpdatedAt\":false},{\"name\":\"sipUsername\",\"kind\":\"scalar\",\"isList\":false,\"isRequired\":false,\"isUnique\":false,\"isId\":false,\"isReadOnly\":false,\"hasDefaultValue\":false,\"type\":\"String\",\"isGenerated\":false,\"isUpdatedAt\":false},{\"name\":\"sipPasswordEncrypted\",\"kind\":\"scalar\",\"isList\":false,\"isRequired\":false,\"isUnique\":false,\"isId\":false,\"isReadOnly\":false,\"hasDefaultValue\":false,\"type\":\"String\",\"isGenerated\":false,\"isUpdatedAt\":false},{\"name\":\"sipServer\",\"kind\":\"scalar\",\"isList\":false,\"isRequired\":false,\"isUnique\":false,\"isId\":false,\"isReadOnly\":false,\"hasDefaultValue\":false,\"type\":\"String\",\"isGenerated\":false,\"isUpdatedAt\":false}],\"primaryKey\":null,\"uniqueFields\":[],\"uniqueIndexes\":[],\"isGenerated\":false},\"MobileContractDetails\":{\"dbName\":null,\"fields\":[{\"name\":\"id\",\"kind\":\"scalar\",\"isList\":false,\"isRequired\":true,\"isUnique\":false,\"isId\":true,\"isReadOnly\":false,\"hasDefaultValue\":true,\"type\":\"Int\",\"default\":{\"name\":\"autoincrement\",\"args\":[]},\"isGenerated\":false,\"isUpdatedAt\":false},{\"name\":\"contractId\",\"kind\":\"scalar\",\"isList\":false,\"isRequired\":true,\"isUnique\":true,\"isId\":false,\"isReadOnly\":true,\"hasDefaultValue\":false,\"type\":\"Int\",\"isGenerated\":false,\"isUpdatedAt\":false},{\"name\":\"contract\",\"kind\":\"object\",\"isList\":false,\"isRequired\":true,\"isUnique\":false,\"isId\":false,\"isReadOnly\":false,\"hasDefaultValue\":false,\"type\":\"Contract\",\"relationName\":\"ContractToMobileContractDetails\",\"relationFromFields\":[\"contractId\"],\"relationToFields\":[\"id\"],\"relationOnDelete\":\"Cascade\",\"isGenerated\":false,\"isUpdatedAt\":false},{\"name\":\"requiresMultisim\",\"kind\":\"scalar\",\"isList\":false,\"isRequired\":true,\"isUnique\":false,\"isId\":false,\"isReadOnly\":false,\"hasDefaultValue\":true,\"type\":\"Boolean\",\"default\":false,\"isGenerated\":false,\"isUpdatedAt\":false},{\"name\":\"dataVolume\",\"kind\":\"scalar\",\"isList\":false,\"isRequired\":false,\"isUnique\":false,\"isId\":false,\"isReadOnly\":false,\"hasDefaultValue\":false,\"type\":\"Float\",\"isGenerated\":false,\"isUpdatedAt\":false},{\"name\":\"includedMinutes\",\"kind\":\"scalar\",\"isList\":false,\"isRequired\":false,\"isUnique\":false,\"isId\":false,\"isReadOnly\":false,\"hasDefaultValue\":false,\"type\":\"Int\",\"isGenerated\":false,\"isUpdatedAt\":false},{\"name\":\"includedSMS\",\"kind\":\"scalar\",\"isList\":false,\"isRequired\":false,\"isUnique\":false,\"isId\":false,\"isReadOnly\":false,\"hasDefaultValue\":false,\"type\":\"Int\",\"isGenerated\":false,\"isUpdatedAt\":false},{\"name\":\"deviceModel\",\"kind\":\"scalar\",\"isList\":false,\"isRequired\":false,\"isUnique\":false,\"isId\":false,\"isReadOnly\":false,\"hasDefaultValue\":false,\"type\":\"String\",\"isGenerated\":false,\"isUpdatedAt\":false},{\"name\":\"deviceImei\",\"kind\":\"scalar\",\"isList\":false,\"isRequired\":false,\"isUnique\":false,\"isId\":false,\"isReadOnly\":false,\"hasDefaultValue\":false,\"type\":\"String\",\"isGenerated\":false,\"isUpdatedAt\":false},{\"name\":\"simCards\",\"kind\":\"object\",\"isList\":true,\"isRequired\":true,\"isUnique\":false,\"isId\":false,\"isReadOnly\":false,\"hasDefaultValue\":false,\"type\":\"SimCard\",\"relationName\":\"MobileContractDetailsToSimCard\",\"relationFromFields\":[],\"relationToFields\":[],\"isGenerated\":false,\"isUpdatedAt\":false},{\"name\":\"phoneNumber\",\"kind\":\"scalar\",\"isList\":false,\"isRequired\":false,\"isUnique\":false,\"isId\":false,\"isReadOnly\":false,\"hasDefaultValue\":false,\"type\":\"String\",\"isGenerated\":false,\"isUpdatedAt\":false},{\"name\":\"simCardNumber\",\"kind\":\"scalar\",\"isList\":false,\"isRequired\":false,\"isUnique\":false,\"isId\":false,\"isReadOnly\":false,\"hasDefaultValue\":false,\"type\":\"String\",\"isGenerated\":false,\"isUpdatedAt\":false}],\"primaryKey\":null,\"uniqueFields\":[],\"uniqueIndexes\":[],\"isGenerated\":false},\"SimCard\":{\"dbName\":null,\"fields\":[{\"name\":\"id\",\"kind\":\"scalar\",\"isList\":false,\"isRequired\":true,\"isUnique\":false,\"isId\":true,\"isReadOnly\":false,\"hasDefaultValue\":true,\"type\":\"Int\",\"default\":{\"name\":\"autoincrement\",\"args\":[]},\"isGenerated\":false,\"isUpdatedAt\":false},{\"name\":\"mobileDetailsId\",\"kind\":\"scalar\",\"isList\":false,\"isRequired\":true,\"isUnique\":false,\"isId\":false,\"isReadOnly\":true,\"hasDefaultValue\":false,\"type\":\"Int\",\"isGenerated\":false,\"isUpdatedAt\":false},{\"name\":\"mobileDetails\",\"kind\":\"object\",\"isList\":false,\"isRequired\":true,\"isUnique\":false,\"isId\":false,\"isReadOnly\":false,\"hasDefaultValue\":false,\"type\":\"MobileContractDetails\",\"relationName\":\"MobileContractDetailsToSimCard\",\"relationFromFields\":[\"mobileDetailsId\"],\"relationToFields\":[\"id\"],\"relationOnDelete\":\"Cascade\",\"isGenerated\":false,\"isUpdatedAt\":false},{\"name\":\"phoneNumber\",\"kind\":\"scalar\",\"isList\":false,\"isRequired\":false,\"isUnique\":false,\"isId\":false,\"isReadOnly\":false,\"hasDefaultValue\":false,\"type\":\"String\",\"isGenerated\":false,\"isUpdatedAt\":false},{\"name\":\"simCardNumber\",\"kind\":\"scalar\",\"isList\":false,\"isRequired\":false,\"isUnique\":false,\"isId\":false,\"isReadOnly\":false,\"hasDefaultValue\":false,\"type\":\"String\",\"isGenerated\":false,\"isUpdatedAt\":false},{\"name\":\"pin\",\"kind\":\"scalar\",\"isList\":false,\"isRequired\":false,\"isUnique\":false,\"isId\":false,\"isReadOnly\":false,\"hasDefaultValue\":false,\"type\":\"String\",\"isGenerated\":false,\"isUpdatedAt\":false},{\"name\":\"puk\",\"kind\":\"scalar\",\"isList\":false,\"isRequired\":false,\"isUnique\":false,\"isId\":false,\"isReadOnly\":false,\"hasDefaultValue\":false,\"type\":\"String\",\"isGenerated\":false,\"isUpdatedAt\":false},{\"name\":\"isMultisim\",\"kind\":\"scalar\",\"isList\":false,\"isRequired\":true,\"isUnique\":false,\"isId\":false,\"isReadOnly\":false,\"hasDefaultValue\":true,\"type\":\"Boolean\",\"default\":false,\"isGenerated\":false,\"isUpdatedAt\":false},{\"name\":\"isMain\",\"kind\":\"scalar\",\"isList\":false,\"isRequired\":true,\"isUnique\":false,\"isId\":false,\"isReadOnly\":false,\"hasDefaultValue\":true,\"type\":\"Boolean\",\"default\":false,\"isGenerated\":false,\"isUpdatedAt\":false},{\"name\":\"createdAt\",\"kind\":\"scalar\",\"isList\":false,\"isRequired\":true,\"isUnique\":false,\"isId\":false,\"isReadOnly\":false,\"hasDefaultValue\":true,\"type\":\"DateTime\",\"default\":{\"name\":\"now\",\"args\":[]},\"isGenerated\":false,\"isUpdatedAt\":false},{\"name\":\"updatedAt\",\"kind\":\"scalar\",\"isList\":false,\"isRequired\":true,\"isUnique\":false,\"isId\":false,\"isReadOnly\":false,\"hasDefaultValue\":false,\"type\":\"DateTime\",\"isGenerated\":false,\"isUpdatedAt\":true}],\"primaryKey\":null,\"uniqueFields\":[],\"uniqueIndexes\":[],\"isGenerated\":false},\"TvContractDetails\":{\"dbName\":null,\"fields\":[{\"name\":\"id\",\"kind\":\"scalar\",\"isList\":false,\"isRequired\":true,\"isUnique\":false,\"isId\":true,\"isReadOnly\":false,\"hasDefaultValue\":true,\"type\":\"Int\",\"default\":{\"name\":\"autoincrement\",\"args\":[]},\"isGenerated\":false,\"isUpdatedAt\":false},{\"name\":\"contractId\",\"kind\":\"scalar\",\"isList\":false,\"isRequired\":true,\"isUnique\":true,\"isId\":false,\"isReadOnly\":true,\"hasDefaultValue\":false,\"type\":\"Int\",\"isGenerated\":false,\"isUpdatedAt\":false},{\"name\":\"contract\",\"kind\":\"object\",\"isList\":false,\"isRequired\":true,\"isUnique\":false,\"isId\":false,\"isReadOnly\":false,\"hasDefaultValue\":false,\"type\":\"Contract\",\"relationName\":\"ContractToTvContractDetails\",\"relationFromFields\":[\"contractId\"],\"relationToFields\":[\"id\"],\"relationOnDelete\":\"Cascade\",\"isGenerated\":false,\"isUpdatedAt\":false},{\"name\":\"receiverModel\",\"kind\":\"scalar\",\"isList\":false,\"isRequired\":false,\"isUnique\":false,\"isId\":false,\"isReadOnly\":false,\"hasDefaultValue\":false,\"type\":\"String\",\"isGenerated\":false,\"isUpdatedAt\":false},{\"name\":\"smartcardNumber\",\"kind\":\"scalar\",\"isList\":false,\"isRequired\":false,\"isUnique\":false,\"isId\":false,\"isReadOnly\":false,\"hasDefaultValue\":false,\"type\":\"String\",\"isGenerated\":false,\"isUpdatedAt\":false},{\"name\":\"package\",\"kind\":\"scalar\",\"isList\":false,\"isRequired\":false,\"isUnique\":false,\"isId\":false,\"isReadOnly\":false,\"hasDefaultValue\":false,\"type\":\"String\",\"isGenerated\":false,\"isUpdatedAt\":false}],\"primaryKey\":null,\"uniqueFields\":[],\"uniqueIndexes\":[],\"isGenerated\":false},\"CarInsuranceDetails\":{\"dbName\":null,\"fields\":[{\"name\":\"id\",\"kind\":\"scalar\",\"isList\":false,\"isRequired\":true,\"isUnique\":false,\"isId\":true,\"isReadOnly\":false,\"hasDefaultValue\":true,\"type\":\"Int\",\"default\":{\"name\":\"autoincrement\",\"args\":[]},\"isGenerated\":false,\"isUpdatedAt\":false},{\"name\":\"contractId\",\"kind\":\"scalar\",\"isList\":false,\"isRequired\":true,\"isUnique\":true,\"isId\":false,\"isReadOnly\":true,\"hasDefaultValue\":false,\"type\":\"Int\",\"isGenerated\":false,\"isUpdatedAt\":false},{\"name\":\"contract\",\"kind\":\"object\",\"isList\":false,\"isRequired\":true,\"isUnique\":false,\"isId\":false,\"isReadOnly\":false,\"hasDefaultValue\":false,\"type\":\"Contract\",\"relationName\":\"CarInsuranceDetailsToContract\",\"relationFromFields\":[\"contractId\"],\"relationToFields\":[\"id\"],\"relationOnDelete\":\"Cascade\",\"isGenerated\":false,\"isUpdatedAt\":false},{\"name\":\"licensePlate\",\"kind\":\"scalar\",\"isList\":false,\"isRequired\":false,\"isUnique\":false,\"isId\":false,\"isReadOnly\":false,\"hasDefaultValue\":false,\"type\":\"String\",\"isGenerated\":false,\"isUpdatedAt\":false},{\"name\":\"hsn\",\"kind\":\"scalar\",\"isList\":false,\"isRequired\":false,\"isUnique\":false,\"isId\":false,\"isReadOnly\":false,\"hasDefaultValue\":false,\"type\":\"String\",\"isGenerated\":false,\"isUpdatedAt\":false},{\"name\":\"tsn\",\"kind\":\"scalar\",\"isList\":false,\"isRequired\":false,\"isUnique\":false,\"isId\":false,\"isReadOnly\":false,\"hasDefaultValue\":false,\"type\":\"String\",\"isGenerated\":false,\"isUpdatedAt\":false},{\"name\":\"vin\",\"kind\":\"scalar\",\"isList\":false,\"isRequired\":false,\"isUnique\":false,\"isId\":false,\"isReadOnly\":false,\"hasDefaultValue\":false,\"type\":\"String\",\"isGenerated\":false,\"isUpdatedAt\":false},{\"name\":\"vehicleType\",\"kind\":\"scalar\",\"isList\":false,\"isRequired\":false,\"isUnique\":false,\"isId\":false,\"isReadOnly\":false,\"hasDefaultValue\":false,\"type\":\"String\",\"isGenerated\":false,\"isUpdatedAt\":false},{\"name\":\"firstRegistration\",\"kind\":\"scalar\",\"isList\":false,\"isRequired\":false,\"isUnique\":false,\"isId\":false,\"isReadOnly\":false,\"hasDefaultValue\":false,\"type\":\"DateTime\",\"isGenerated\":false,\"isUpdatedAt\":false},{\"name\":\"noClaimsClass\",\"kind\":\"scalar\",\"isList\":false,\"isRequired\":false,\"isUnique\":false,\"isId\":false,\"isReadOnly\":false,\"hasDefaultValue\":false,\"type\":\"String\",\"isGenerated\":false,\"isUpdatedAt\":false},{\"name\":\"insuranceType\",\"kind\":\"enum\",\"isList\":false,\"isRequired\":true,\"isUnique\":false,\"isId\":false,\"isReadOnly\":false,\"hasDefaultValue\":true,\"type\":\"InsuranceType\",\"default\":\"LIABILITY\",\"isGenerated\":false,\"isUpdatedAt\":false},{\"name\":\"deductiblePartial\",\"kind\":\"scalar\",\"isList\":false,\"isRequired\":false,\"isUnique\":false,\"isId\":false,\"isReadOnly\":false,\"hasDefaultValue\":false,\"type\":\"Float\",\"isGenerated\":false,\"isUpdatedAt\":false},{\"name\":\"deductibleFull\",\"kind\":\"scalar\",\"isList\":false,\"isRequired\":false,\"isUnique\":false,\"isId\":false,\"isReadOnly\":false,\"hasDefaultValue\":false,\"type\":\"Float\",\"isGenerated\":false,\"isUpdatedAt\":false},{\"name\":\"policyNumber\",\"kind\":\"scalar\",\"isList\":false,\"isRequired\":false,\"isUnique\":false,\"isId\":false,\"isReadOnly\":false,\"hasDefaultValue\":false,\"type\":\"String\",\"isGenerated\":false,\"isUpdatedAt\":false},{\"name\":\"previousInsurer\",\"kind\":\"scalar\",\"isList\":false,\"isRequired\":false,\"isUnique\":false,\"isId\":false,\"isReadOnly\":false,\"hasDefaultValue\":false,\"type\":\"String\",\"isGenerated\":false,\"isUpdatedAt\":false}],\"primaryKey\":null,\"uniqueFields\":[],\"uniqueIndexes\":[],\"isGenerated\":false}},\"enums\":{\"CustomerType\":{\"values\":[{\"name\":\"PRIVATE\",\"dbName\":null},{\"name\":\"BUSINESS\",\"dbName\":null}],\"dbName\":null},\"AddressType\":{\"values\":[{\"name\":\"DELIVERY_RESIDENCE\",\"dbName\":null},{\"name\":\"BILLING\",\"dbName\":null}],\"dbName\":null},\"DocumentType\":{\"values\":[{\"name\":\"ID_CARD\",\"dbName\":null},{\"name\":\"PASSPORT\",\"dbName\":null},{\"name\":\"DRIVERS_LICENSE\",\"dbName\":null},{\"name\":\"OTHER\",\"dbName\":null}],\"dbName\":null},\"EmailProviderType\":{\"values\":[{\"name\":\"PLESK\",\"dbName\":null},{\"name\":\"CPANEL\",\"dbName\":null},{\"name\":\"DIRECTADMIN\",\"dbName\":null}],\"dbName\":null},\"MeterType\":{\"values\":[{\"name\":\"ELECTRICITY\",\"dbName\":null},{\"name\":\"GAS\",\"dbName\":null}],\"dbName\":null},\"ContractType\":{\"values\":[{\"name\":\"ELECTRICITY\",\"dbName\":null},{\"name\":\"GAS\",\"dbName\":null},{\"name\":\"DSL\",\"dbName\":null},{\"name\":\"CABLE\",\"dbName\":null},{\"name\":\"FIBER\",\"dbName\":null},{\"name\":\"MOBILE\",\"dbName\":null},{\"name\":\"TV\",\"dbName\":null},{\"name\":\"CAR_INSURANCE\",\"dbName\":null}],\"dbName\":null},\"ContractStatus\":{\"values\":[{\"name\":\"DRAFT\",\"dbName\":null},{\"name\":\"PENDING\",\"dbName\":null},{\"name\":\"ACTIVE\",\"dbName\":null},{\"name\":\"CANCELLED\",\"dbName\":null},{\"name\":\"EXPIRED\",\"dbName\":null},{\"name\":\"DEACTIVATED\",\"dbName\":null}],\"dbName\":null},\"ContractTaskStatus\":{\"values\":[{\"name\":\"OPEN\",\"dbName\":null},{\"name\":\"COMPLETED\",\"dbName\":null}],\"dbName\":null},\"InsuranceType\":{\"values\":[{\"name\":\"LIABILITY\",\"dbName\":null},{\"name\":\"PARTIAL\",\"dbName\":null},{\"name\":\"FULL\",\"dbName\":null}],\"dbName\":null}},\"types\":{}}") +config.runtimeDataModel = JSON.parse("{\"models\":{\"AppSetting\":{\"dbName\":null,\"fields\":[{\"name\":\"id\",\"kind\":\"scalar\",\"isList\":false,\"isRequired\":true,\"isUnique\":false,\"isId\":true,\"isReadOnly\":false,\"hasDefaultValue\":true,\"type\":\"Int\",\"default\":{\"name\":\"autoincrement\",\"args\":[]},\"isGenerated\":false,\"isUpdatedAt\":false},{\"name\":\"key\",\"kind\":\"scalar\",\"isList\":false,\"isRequired\":true,\"isUnique\":true,\"isId\":false,\"isReadOnly\":false,\"hasDefaultValue\":false,\"type\":\"String\",\"isGenerated\":false,\"isUpdatedAt\":false},{\"name\":\"value\",\"kind\":\"scalar\",\"isList\":false,\"isRequired\":true,\"isUnique\":false,\"isId\":false,\"isReadOnly\":false,\"hasDefaultValue\":false,\"type\":\"String\",\"isGenerated\":false,\"isUpdatedAt\":false},{\"name\":\"createdAt\",\"kind\":\"scalar\",\"isList\":false,\"isRequired\":true,\"isUnique\":false,\"isId\":false,\"isReadOnly\":false,\"hasDefaultValue\":true,\"type\":\"DateTime\",\"default\":{\"name\":\"now\",\"args\":[]},\"isGenerated\":false,\"isUpdatedAt\":false},{\"name\":\"updatedAt\",\"kind\":\"scalar\",\"isList\":false,\"isRequired\":true,\"isUnique\":false,\"isId\":false,\"isReadOnly\":false,\"hasDefaultValue\":false,\"type\":\"DateTime\",\"isGenerated\":false,\"isUpdatedAt\":true}],\"primaryKey\":null,\"uniqueFields\":[],\"uniqueIndexes\":[],\"isGenerated\":false},\"User\":{\"dbName\":null,\"fields\":[{\"name\":\"id\",\"kind\":\"scalar\",\"isList\":false,\"isRequired\":true,\"isUnique\":false,\"isId\":true,\"isReadOnly\":false,\"hasDefaultValue\":true,\"type\":\"Int\",\"default\":{\"name\":\"autoincrement\",\"args\":[]},\"isGenerated\":false,\"isUpdatedAt\":false},{\"name\":\"email\",\"kind\":\"scalar\",\"isList\":false,\"isRequired\":true,\"isUnique\":true,\"isId\":false,\"isReadOnly\":false,\"hasDefaultValue\":false,\"type\":\"String\",\"isGenerated\":false,\"isUpdatedAt\":false},{\"name\":\"password\",\"kind\":\"scalar\",\"isList\":false,\"isRequired\":true,\"isUnique\":false,\"isId\":false,\"isReadOnly\":false,\"hasDefaultValue\":false,\"type\":\"String\",\"isGenerated\":false,\"isUpdatedAt\":false},{\"name\":\"firstName\",\"kind\":\"scalar\",\"isList\":false,\"isRequired\":true,\"isUnique\":false,\"isId\":false,\"isReadOnly\":false,\"hasDefaultValue\":false,\"type\":\"String\",\"isGenerated\":false,\"isUpdatedAt\":false},{\"name\":\"lastName\",\"kind\":\"scalar\",\"isList\":false,\"isRequired\":true,\"isUnique\":false,\"isId\":false,\"isReadOnly\":false,\"hasDefaultValue\":false,\"type\":\"String\",\"isGenerated\":false,\"isUpdatedAt\":false},{\"name\":\"isActive\",\"kind\":\"scalar\",\"isList\":false,\"isRequired\":true,\"isUnique\":false,\"isId\":false,\"isReadOnly\":false,\"hasDefaultValue\":true,\"type\":\"Boolean\",\"default\":true,\"isGenerated\":false,\"isUpdatedAt\":false},{\"name\":\"tokenInvalidatedAt\",\"kind\":\"scalar\",\"isList\":false,\"isRequired\":false,\"isUnique\":false,\"isId\":false,\"isReadOnly\":false,\"hasDefaultValue\":false,\"type\":\"DateTime\",\"isGenerated\":false,\"isUpdatedAt\":false},{\"name\":\"customerId\",\"kind\":\"scalar\",\"isList\":false,\"isRequired\":false,\"isUnique\":true,\"isId\":false,\"isReadOnly\":true,\"hasDefaultValue\":false,\"type\":\"Int\",\"isGenerated\":false,\"isUpdatedAt\":false},{\"name\":\"customer\",\"kind\":\"object\",\"isList\":false,\"isRequired\":false,\"isUnique\":false,\"isId\":false,\"isReadOnly\":false,\"hasDefaultValue\":false,\"type\":\"Customer\",\"relationName\":\"CustomerToUser\",\"relationFromFields\":[\"customerId\"],\"relationToFields\":[\"id\"],\"isGenerated\":false,\"isUpdatedAt\":false},{\"name\":\"roles\",\"kind\":\"object\",\"isList\":true,\"isRequired\":true,\"isUnique\":false,\"isId\":false,\"isReadOnly\":false,\"hasDefaultValue\":false,\"type\":\"UserRole\",\"relationName\":\"UserToUserRole\",\"relationFromFields\":[],\"relationToFields\":[],\"isGenerated\":false,\"isUpdatedAt\":false},{\"name\":\"createdAt\",\"kind\":\"scalar\",\"isList\":false,\"isRequired\":true,\"isUnique\":false,\"isId\":false,\"isReadOnly\":false,\"hasDefaultValue\":true,\"type\":\"DateTime\",\"default\":{\"name\":\"now\",\"args\":[]},\"isGenerated\":false,\"isUpdatedAt\":false},{\"name\":\"updatedAt\",\"kind\":\"scalar\",\"isList\":false,\"isRequired\":true,\"isUnique\":false,\"isId\":false,\"isReadOnly\":false,\"hasDefaultValue\":false,\"type\":\"DateTime\",\"isGenerated\":false,\"isUpdatedAt\":true}],\"primaryKey\":null,\"uniqueFields\":[],\"uniqueIndexes\":[],\"isGenerated\":false},\"Role\":{\"dbName\":null,\"fields\":[{\"name\":\"id\",\"kind\":\"scalar\",\"isList\":false,\"isRequired\":true,\"isUnique\":false,\"isId\":true,\"isReadOnly\":false,\"hasDefaultValue\":true,\"type\":\"Int\",\"default\":{\"name\":\"autoincrement\",\"args\":[]},\"isGenerated\":false,\"isUpdatedAt\":false},{\"name\":\"name\",\"kind\":\"scalar\",\"isList\":false,\"isRequired\":true,\"isUnique\":true,\"isId\":false,\"isReadOnly\":false,\"hasDefaultValue\":false,\"type\":\"String\",\"isGenerated\":false,\"isUpdatedAt\":false},{\"name\":\"description\",\"kind\":\"scalar\",\"isList\":false,\"isRequired\":false,\"isUnique\":false,\"isId\":false,\"isReadOnly\":false,\"hasDefaultValue\":false,\"type\":\"String\",\"isGenerated\":false,\"isUpdatedAt\":false},{\"name\":\"permissions\",\"kind\":\"object\",\"isList\":true,\"isRequired\":true,\"isUnique\":false,\"isId\":false,\"isReadOnly\":false,\"hasDefaultValue\":false,\"type\":\"RolePermission\",\"relationName\":\"RoleToRolePermission\",\"relationFromFields\":[],\"relationToFields\":[],\"isGenerated\":false,\"isUpdatedAt\":false},{\"name\":\"users\",\"kind\":\"object\",\"isList\":true,\"isRequired\":true,\"isUnique\":false,\"isId\":false,\"isReadOnly\":false,\"hasDefaultValue\":false,\"type\":\"UserRole\",\"relationName\":\"RoleToUserRole\",\"relationFromFields\":[],\"relationToFields\":[],\"isGenerated\":false,\"isUpdatedAt\":false},{\"name\":\"createdAt\",\"kind\":\"scalar\",\"isList\":false,\"isRequired\":true,\"isUnique\":false,\"isId\":false,\"isReadOnly\":false,\"hasDefaultValue\":true,\"type\":\"DateTime\",\"default\":{\"name\":\"now\",\"args\":[]},\"isGenerated\":false,\"isUpdatedAt\":false},{\"name\":\"updatedAt\",\"kind\":\"scalar\",\"isList\":false,\"isRequired\":true,\"isUnique\":false,\"isId\":false,\"isReadOnly\":false,\"hasDefaultValue\":false,\"type\":\"DateTime\",\"isGenerated\":false,\"isUpdatedAt\":true}],\"primaryKey\":null,\"uniqueFields\":[],\"uniqueIndexes\":[],\"isGenerated\":false},\"Permission\":{\"dbName\":null,\"fields\":[{\"name\":\"id\",\"kind\":\"scalar\",\"isList\":false,\"isRequired\":true,\"isUnique\":false,\"isId\":true,\"isReadOnly\":false,\"hasDefaultValue\":true,\"type\":\"Int\",\"default\":{\"name\":\"autoincrement\",\"args\":[]},\"isGenerated\":false,\"isUpdatedAt\":false},{\"name\":\"resource\",\"kind\":\"scalar\",\"isList\":false,\"isRequired\":true,\"isUnique\":false,\"isId\":false,\"isReadOnly\":false,\"hasDefaultValue\":false,\"type\":\"String\",\"isGenerated\":false,\"isUpdatedAt\":false},{\"name\":\"action\",\"kind\":\"scalar\",\"isList\":false,\"isRequired\":true,\"isUnique\":false,\"isId\":false,\"isReadOnly\":false,\"hasDefaultValue\":false,\"type\":\"String\",\"isGenerated\":false,\"isUpdatedAt\":false},{\"name\":\"roles\",\"kind\":\"object\",\"isList\":true,\"isRequired\":true,\"isUnique\":false,\"isId\":false,\"isReadOnly\":false,\"hasDefaultValue\":false,\"type\":\"RolePermission\",\"relationName\":\"PermissionToRolePermission\",\"relationFromFields\":[],\"relationToFields\":[],\"isGenerated\":false,\"isUpdatedAt\":false}],\"primaryKey\":null,\"uniqueFields\":[[\"resource\",\"action\"]],\"uniqueIndexes\":[{\"name\":null,\"fields\":[\"resource\",\"action\"]}],\"isGenerated\":false},\"RolePermission\":{\"dbName\":null,\"fields\":[{\"name\":\"roleId\",\"kind\":\"scalar\",\"isList\":false,\"isRequired\":true,\"isUnique\":false,\"isId\":false,\"isReadOnly\":true,\"hasDefaultValue\":false,\"type\":\"Int\",\"isGenerated\":false,\"isUpdatedAt\":false},{\"name\":\"permissionId\",\"kind\":\"scalar\",\"isList\":false,\"isRequired\":true,\"isUnique\":false,\"isId\":false,\"isReadOnly\":true,\"hasDefaultValue\":false,\"type\":\"Int\",\"isGenerated\":false,\"isUpdatedAt\":false},{\"name\":\"role\",\"kind\":\"object\",\"isList\":false,\"isRequired\":true,\"isUnique\":false,\"isId\":false,\"isReadOnly\":false,\"hasDefaultValue\":false,\"type\":\"Role\",\"relationName\":\"RoleToRolePermission\",\"relationFromFields\":[\"roleId\"],\"relationToFields\":[\"id\"],\"relationOnDelete\":\"Cascade\",\"isGenerated\":false,\"isUpdatedAt\":false},{\"name\":\"permission\",\"kind\":\"object\",\"isList\":false,\"isRequired\":true,\"isUnique\":false,\"isId\":false,\"isReadOnly\":false,\"hasDefaultValue\":false,\"type\":\"Permission\",\"relationName\":\"PermissionToRolePermission\",\"relationFromFields\":[\"permissionId\"],\"relationToFields\":[\"id\"],\"relationOnDelete\":\"Cascade\",\"isGenerated\":false,\"isUpdatedAt\":false}],\"primaryKey\":{\"name\":null,\"fields\":[\"roleId\",\"permissionId\"]},\"uniqueFields\":[],\"uniqueIndexes\":[],\"isGenerated\":false},\"UserRole\":{\"dbName\":null,\"fields\":[{\"name\":\"userId\",\"kind\":\"scalar\",\"isList\":false,\"isRequired\":true,\"isUnique\":false,\"isId\":false,\"isReadOnly\":true,\"hasDefaultValue\":false,\"type\":\"Int\",\"isGenerated\":false,\"isUpdatedAt\":false},{\"name\":\"roleId\",\"kind\":\"scalar\",\"isList\":false,\"isRequired\":true,\"isUnique\":false,\"isId\":false,\"isReadOnly\":true,\"hasDefaultValue\":false,\"type\":\"Int\",\"isGenerated\":false,\"isUpdatedAt\":false},{\"name\":\"user\",\"kind\":\"object\",\"isList\":false,\"isRequired\":true,\"isUnique\":false,\"isId\":false,\"isReadOnly\":false,\"hasDefaultValue\":false,\"type\":\"User\",\"relationName\":\"UserToUserRole\",\"relationFromFields\":[\"userId\"],\"relationToFields\":[\"id\"],\"relationOnDelete\":\"Cascade\",\"isGenerated\":false,\"isUpdatedAt\":false},{\"name\":\"role\",\"kind\":\"object\",\"isList\":false,\"isRequired\":true,\"isUnique\":false,\"isId\":false,\"isReadOnly\":false,\"hasDefaultValue\":false,\"type\":\"Role\",\"relationName\":\"RoleToUserRole\",\"relationFromFields\":[\"roleId\"],\"relationToFields\":[\"id\"],\"relationOnDelete\":\"Cascade\",\"isGenerated\":false,\"isUpdatedAt\":false}],\"primaryKey\":{\"name\":null,\"fields\":[\"userId\",\"roleId\"]},\"uniqueFields\":[],\"uniqueIndexes\":[],\"isGenerated\":false},\"Customer\":{\"dbName\":null,\"fields\":[{\"name\":\"id\",\"kind\":\"scalar\",\"isList\":false,\"isRequired\":true,\"isUnique\":false,\"isId\":true,\"isReadOnly\":false,\"hasDefaultValue\":true,\"type\":\"Int\",\"default\":{\"name\":\"autoincrement\",\"args\":[]},\"isGenerated\":false,\"isUpdatedAt\":false},{\"name\":\"customerNumber\",\"kind\":\"scalar\",\"isList\":false,\"isRequired\":true,\"isUnique\":true,\"isId\":false,\"isReadOnly\":false,\"hasDefaultValue\":false,\"type\":\"String\",\"isGenerated\":false,\"isUpdatedAt\":false},{\"name\":\"type\",\"kind\":\"enum\",\"isList\":false,\"isRequired\":true,\"isUnique\":false,\"isId\":false,\"isReadOnly\":false,\"hasDefaultValue\":true,\"type\":\"CustomerType\",\"default\":\"PRIVATE\",\"isGenerated\":false,\"isUpdatedAt\":false},{\"name\":\"salutation\",\"kind\":\"scalar\",\"isList\":false,\"isRequired\":false,\"isUnique\":false,\"isId\":false,\"isReadOnly\":false,\"hasDefaultValue\":false,\"type\":\"String\",\"isGenerated\":false,\"isUpdatedAt\":false},{\"name\":\"firstName\",\"kind\":\"scalar\",\"isList\":false,\"isRequired\":true,\"isUnique\":false,\"isId\":false,\"isReadOnly\":false,\"hasDefaultValue\":false,\"type\":\"String\",\"isGenerated\":false,\"isUpdatedAt\":false},{\"name\":\"lastName\",\"kind\":\"scalar\",\"isList\":false,\"isRequired\":true,\"isUnique\":false,\"isId\":false,\"isReadOnly\":false,\"hasDefaultValue\":false,\"type\":\"String\",\"isGenerated\":false,\"isUpdatedAt\":false},{\"name\":\"companyName\",\"kind\":\"scalar\",\"isList\":false,\"isRequired\":false,\"isUnique\":false,\"isId\":false,\"isReadOnly\":false,\"hasDefaultValue\":false,\"type\":\"String\",\"isGenerated\":false,\"isUpdatedAt\":false},{\"name\":\"foundingDate\",\"kind\":\"scalar\",\"isList\":false,\"isRequired\":false,\"isUnique\":false,\"isId\":false,\"isReadOnly\":false,\"hasDefaultValue\":false,\"type\":\"DateTime\",\"isGenerated\":false,\"isUpdatedAt\":false},{\"name\":\"birthDate\",\"kind\":\"scalar\",\"isList\":false,\"isRequired\":false,\"isUnique\":false,\"isId\":false,\"isReadOnly\":false,\"hasDefaultValue\":false,\"type\":\"DateTime\",\"isGenerated\":false,\"isUpdatedAt\":false},{\"name\":\"birthPlace\",\"kind\":\"scalar\",\"isList\":false,\"isRequired\":false,\"isUnique\":false,\"isId\":false,\"isReadOnly\":false,\"hasDefaultValue\":false,\"type\":\"String\",\"isGenerated\":false,\"isUpdatedAt\":false},{\"name\":\"email\",\"kind\":\"scalar\",\"isList\":false,\"isRequired\":false,\"isUnique\":false,\"isId\":false,\"isReadOnly\":false,\"hasDefaultValue\":false,\"type\":\"String\",\"isGenerated\":false,\"isUpdatedAt\":false},{\"name\":\"phone\",\"kind\":\"scalar\",\"isList\":false,\"isRequired\":false,\"isUnique\":false,\"isId\":false,\"isReadOnly\":false,\"hasDefaultValue\":false,\"type\":\"String\",\"isGenerated\":false,\"isUpdatedAt\":false},{\"name\":\"mobile\",\"kind\":\"scalar\",\"isList\":false,\"isRequired\":false,\"isUnique\":false,\"isId\":false,\"isReadOnly\":false,\"hasDefaultValue\":false,\"type\":\"String\",\"isGenerated\":false,\"isUpdatedAt\":false},{\"name\":\"taxNumber\",\"kind\":\"scalar\",\"isList\":false,\"isRequired\":false,\"isUnique\":false,\"isId\":false,\"isReadOnly\":false,\"hasDefaultValue\":false,\"type\":\"String\",\"isGenerated\":false,\"isUpdatedAt\":false},{\"name\":\"businessRegistrationPath\",\"kind\":\"scalar\",\"isList\":false,\"isRequired\":false,\"isUnique\":false,\"isId\":false,\"isReadOnly\":false,\"hasDefaultValue\":false,\"type\":\"String\",\"isGenerated\":false,\"isUpdatedAt\":false},{\"name\":\"commercialRegisterPath\",\"kind\":\"scalar\",\"isList\":false,\"isRequired\":false,\"isUnique\":false,\"isId\":false,\"isReadOnly\":false,\"hasDefaultValue\":false,\"type\":\"String\",\"isGenerated\":false,\"isUpdatedAt\":false},{\"name\":\"commercialRegisterNumber\",\"kind\":\"scalar\",\"isList\":false,\"isRequired\":false,\"isUnique\":false,\"isId\":false,\"isReadOnly\":false,\"hasDefaultValue\":false,\"type\":\"String\",\"isGenerated\":false,\"isUpdatedAt\":false},{\"name\":\"privacyPolicyPath\",\"kind\":\"scalar\",\"isList\":false,\"isRequired\":false,\"isUnique\":false,\"isId\":false,\"isReadOnly\":false,\"hasDefaultValue\":false,\"type\":\"String\",\"isGenerated\":false,\"isUpdatedAt\":false},{\"name\":\"notes\",\"kind\":\"scalar\",\"isList\":false,\"isRequired\":false,\"isUnique\":false,\"isId\":false,\"isReadOnly\":false,\"hasDefaultValue\":false,\"type\":\"String\",\"isGenerated\":false,\"isUpdatedAt\":false},{\"name\":\"portalEnabled\",\"kind\":\"scalar\",\"isList\":false,\"isRequired\":true,\"isUnique\":false,\"isId\":false,\"isReadOnly\":false,\"hasDefaultValue\":true,\"type\":\"Boolean\",\"default\":false,\"isGenerated\":false,\"isUpdatedAt\":false},{\"name\":\"portalEmail\",\"kind\":\"scalar\",\"isList\":false,\"isRequired\":false,\"isUnique\":true,\"isId\":false,\"isReadOnly\":false,\"hasDefaultValue\":false,\"type\":\"String\",\"isGenerated\":false,\"isUpdatedAt\":false},{\"name\":\"portalPasswordHash\",\"kind\":\"scalar\",\"isList\":false,\"isRequired\":false,\"isUnique\":false,\"isId\":false,\"isReadOnly\":false,\"hasDefaultValue\":false,\"type\":\"String\",\"isGenerated\":false,\"isUpdatedAt\":false},{\"name\":\"portalPasswordEncrypted\",\"kind\":\"scalar\",\"isList\":false,\"isRequired\":false,\"isUnique\":false,\"isId\":false,\"isReadOnly\":false,\"hasDefaultValue\":false,\"type\":\"String\",\"isGenerated\":false,\"isUpdatedAt\":false},{\"name\":\"portalLastLogin\",\"kind\":\"scalar\",\"isList\":false,\"isRequired\":false,\"isUnique\":false,\"isId\":false,\"isReadOnly\":false,\"hasDefaultValue\":false,\"type\":\"DateTime\",\"isGenerated\":false,\"isUpdatedAt\":false},{\"name\":\"user\",\"kind\":\"object\",\"isList\":false,\"isRequired\":false,\"isUnique\":false,\"isId\":false,\"isReadOnly\":false,\"hasDefaultValue\":false,\"type\":\"User\",\"relationName\":\"CustomerToUser\",\"relationFromFields\":[],\"relationToFields\":[],\"isGenerated\":false,\"isUpdatedAt\":false},{\"name\":\"addresses\",\"kind\":\"object\",\"isList\":true,\"isRequired\":true,\"isUnique\":false,\"isId\":false,\"isReadOnly\":false,\"hasDefaultValue\":false,\"type\":\"Address\",\"relationName\":\"AddressToCustomer\",\"relationFromFields\":[],\"relationToFields\":[],\"isGenerated\":false,\"isUpdatedAt\":false},{\"name\":\"bankCards\",\"kind\":\"object\",\"isList\":true,\"isRequired\":true,\"isUnique\":false,\"isId\":false,\"isReadOnly\":false,\"hasDefaultValue\":false,\"type\":\"BankCard\",\"relationName\":\"BankCardToCustomer\",\"relationFromFields\":[],\"relationToFields\":[],\"isGenerated\":false,\"isUpdatedAt\":false},{\"name\":\"identityDocuments\",\"kind\":\"object\",\"isList\":true,\"isRequired\":true,\"isUnique\":false,\"isId\":false,\"isReadOnly\":false,\"hasDefaultValue\":false,\"type\":\"IdentityDocument\",\"relationName\":\"CustomerToIdentityDocument\",\"relationFromFields\":[],\"relationToFields\":[],\"isGenerated\":false,\"isUpdatedAt\":false},{\"name\":\"meters\",\"kind\":\"object\",\"isList\":true,\"isRequired\":true,\"isUnique\":false,\"isId\":false,\"isReadOnly\":false,\"hasDefaultValue\":false,\"type\":\"Meter\",\"relationName\":\"CustomerToMeter\",\"relationFromFields\":[],\"relationToFields\":[],\"isGenerated\":false,\"isUpdatedAt\":false},{\"name\":\"stressfreiEmails\",\"kind\":\"object\",\"isList\":true,\"isRequired\":true,\"isUnique\":false,\"isId\":false,\"isReadOnly\":false,\"hasDefaultValue\":false,\"type\":\"StressfreiEmail\",\"relationName\":\"CustomerToStressfreiEmail\",\"relationFromFields\":[],\"relationToFields\":[],\"isGenerated\":false,\"isUpdatedAt\":false},{\"name\":\"contracts\",\"kind\":\"object\",\"isList\":true,\"isRequired\":true,\"isUnique\":false,\"isId\":false,\"isReadOnly\":false,\"hasDefaultValue\":false,\"type\":\"Contract\",\"relationName\":\"ContractToCustomer\",\"relationFromFields\":[],\"relationToFields\":[],\"isGenerated\":false,\"isUpdatedAt\":false},{\"name\":\"representingFor\",\"kind\":\"object\",\"isList\":true,\"isRequired\":true,\"isUnique\":false,\"isId\":false,\"isReadOnly\":false,\"hasDefaultValue\":false,\"type\":\"CustomerRepresentative\",\"relationName\":\"RepresentativeCustomer\",\"relationFromFields\":[],\"relationToFields\":[],\"isGenerated\":false,\"isUpdatedAt\":false},{\"name\":\"representedBy\",\"kind\":\"object\",\"isList\":true,\"isRequired\":true,\"isUnique\":false,\"isId\":false,\"isReadOnly\":false,\"hasDefaultValue\":false,\"type\":\"CustomerRepresentative\",\"relationName\":\"RepresentedCustomer\",\"relationFromFields\":[],\"relationToFields\":[],\"isGenerated\":false,\"isUpdatedAt\":false},{\"name\":\"createdAt\",\"kind\":\"scalar\",\"isList\":false,\"isRequired\":true,\"isUnique\":false,\"isId\":false,\"isReadOnly\":false,\"hasDefaultValue\":true,\"type\":\"DateTime\",\"default\":{\"name\":\"now\",\"args\":[]},\"isGenerated\":false,\"isUpdatedAt\":false},{\"name\":\"updatedAt\",\"kind\":\"scalar\",\"isList\":false,\"isRequired\":true,\"isUnique\":false,\"isId\":false,\"isReadOnly\":false,\"hasDefaultValue\":false,\"type\":\"DateTime\",\"isGenerated\":false,\"isUpdatedAt\":true}],\"primaryKey\":null,\"uniqueFields\":[],\"uniqueIndexes\":[],\"isGenerated\":false},\"CustomerRepresentative\":{\"dbName\":null,\"fields\":[{\"name\":\"id\",\"kind\":\"scalar\",\"isList\":false,\"isRequired\":true,\"isUnique\":false,\"isId\":true,\"isReadOnly\":false,\"hasDefaultValue\":true,\"type\":\"Int\",\"default\":{\"name\":\"autoincrement\",\"args\":[]},\"isGenerated\":false,\"isUpdatedAt\":false},{\"name\":\"customerId\",\"kind\":\"scalar\",\"isList\":false,\"isRequired\":true,\"isUnique\":false,\"isId\":false,\"isReadOnly\":true,\"hasDefaultValue\":false,\"type\":\"Int\",\"isGenerated\":false,\"isUpdatedAt\":false},{\"name\":\"customer\",\"kind\":\"object\",\"isList\":false,\"isRequired\":true,\"isUnique\":false,\"isId\":false,\"isReadOnly\":false,\"hasDefaultValue\":false,\"type\":\"Customer\",\"relationName\":\"RepresentedCustomer\",\"relationFromFields\":[\"customerId\"],\"relationToFields\":[\"id\"],\"relationOnDelete\":\"Cascade\",\"isGenerated\":false,\"isUpdatedAt\":false},{\"name\":\"representativeId\",\"kind\":\"scalar\",\"isList\":false,\"isRequired\":true,\"isUnique\":false,\"isId\":false,\"isReadOnly\":true,\"hasDefaultValue\":false,\"type\":\"Int\",\"isGenerated\":false,\"isUpdatedAt\":false},{\"name\":\"representative\",\"kind\":\"object\",\"isList\":false,\"isRequired\":true,\"isUnique\":false,\"isId\":false,\"isReadOnly\":false,\"hasDefaultValue\":false,\"type\":\"Customer\",\"relationName\":\"RepresentativeCustomer\",\"relationFromFields\":[\"representativeId\"],\"relationToFields\":[\"id\"],\"relationOnDelete\":\"Cascade\",\"isGenerated\":false,\"isUpdatedAt\":false},{\"name\":\"notes\",\"kind\":\"scalar\",\"isList\":false,\"isRequired\":false,\"isUnique\":false,\"isId\":false,\"isReadOnly\":false,\"hasDefaultValue\":false,\"type\":\"String\",\"isGenerated\":false,\"isUpdatedAt\":false},{\"name\":\"isActive\",\"kind\":\"scalar\",\"isList\":false,\"isRequired\":true,\"isUnique\":false,\"isId\":false,\"isReadOnly\":false,\"hasDefaultValue\":true,\"type\":\"Boolean\",\"default\":true,\"isGenerated\":false,\"isUpdatedAt\":false},{\"name\":\"createdAt\",\"kind\":\"scalar\",\"isList\":false,\"isRequired\":true,\"isUnique\":false,\"isId\":false,\"isReadOnly\":false,\"hasDefaultValue\":true,\"type\":\"DateTime\",\"default\":{\"name\":\"now\",\"args\":[]},\"isGenerated\":false,\"isUpdatedAt\":false},{\"name\":\"updatedAt\",\"kind\":\"scalar\",\"isList\":false,\"isRequired\":true,\"isUnique\":false,\"isId\":false,\"isReadOnly\":false,\"hasDefaultValue\":false,\"type\":\"DateTime\",\"isGenerated\":false,\"isUpdatedAt\":true}],\"primaryKey\":null,\"uniqueFields\":[[\"customerId\",\"representativeId\"]],\"uniqueIndexes\":[{\"name\":null,\"fields\":[\"customerId\",\"representativeId\"]}],\"isGenerated\":false},\"Address\":{\"dbName\":null,\"fields\":[{\"name\":\"id\",\"kind\":\"scalar\",\"isList\":false,\"isRequired\":true,\"isUnique\":false,\"isId\":true,\"isReadOnly\":false,\"hasDefaultValue\":true,\"type\":\"Int\",\"default\":{\"name\":\"autoincrement\",\"args\":[]},\"isGenerated\":false,\"isUpdatedAt\":false},{\"name\":\"customerId\",\"kind\":\"scalar\",\"isList\":false,\"isRequired\":true,\"isUnique\":false,\"isId\":false,\"isReadOnly\":true,\"hasDefaultValue\":false,\"type\":\"Int\",\"isGenerated\":false,\"isUpdatedAt\":false},{\"name\":\"customer\",\"kind\":\"object\",\"isList\":false,\"isRequired\":true,\"isUnique\":false,\"isId\":false,\"isReadOnly\":false,\"hasDefaultValue\":false,\"type\":\"Customer\",\"relationName\":\"AddressToCustomer\",\"relationFromFields\":[\"customerId\"],\"relationToFields\":[\"id\"],\"relationOnDelete\":\"Cascade\",\"isGenerated\":false,\"isUpdatedAt\":false},{\"name\":\"type\",\"kind\":\"enum\",\"isList\":false,\"isRequired\":true,\"isUnique\":false,\"isId\":false,\"isReadOnly\":false,\"hasDefaultValue\":true,\"type\":\"AddressType\",\"default\":\"DELIVERY_RESIDENCE\",\"isGenerated\":false,\"isUpdatedAt\":false},{\"name\":\"street\",\"kind\":\"scalar\",\"isList\":false,\"isRequired\":true,\"isUnique\":false,\"isId\":false,\"isReadOnly\":false,\"hasDefaultValue\":false,\"type\":\"String\",\"isGenerated\":false,\"isUpdatedAt\":false},{\"name\":\"houseNumber\",\"kind\":\"scalar\",\"isList\":false,\"isRequired\":true,\"isUnique\":false,\"isId\":false,\"isReadOnly\":false,\"hasDefaultValue\":false,\"type\":\"String\",\"isGenerated\":false,\"isUpdatedAt\":false},{\"name\":\"postalCode\",\"kind\":\"scalar\",\"isList\":false,\"isRequired\":true,\"isUnique\":false,\"isId\":false,\"isReadOnly\":false,\"hasDefaultValue\":false,\"type\":\"String\",\"isGenerated\":false,\"isUpdatedAt\":false},{\"name\":\"city\",\"kind\":\"scalar\",\"isList\":false,\"isRequired\":true,\"isUnique\":false,\"isId\":false,\"isReadOnly\":false,\"hasDefaultValue\":false,\"type\":\"String\",\"isGenerated\":false,\"isUpdatedAt\":false},{\"name\":\"country\",\"kind\":\"scalar\",\"isList\":false,\"isRequired\":true,\"isUnique\":false,\"isId\":false,\"isReadOnly\":false,\"hasDefaultValue\":true,\"type\":\"String\",\"default\":\"Deutschland\",\"isGenerated\":false,\"isUpdatedAt\":false},{\"name\":\"isDefault\",\"kind\":\"scalar\",\"isList\":false,\"isRequired\":true,\"isUnique\":false,\"isId\":false,\"isReadOnly\":false,\"hasDefaultValue\":true,\"type\":\"Boolean\",\"default\":false,\"isGenerated\":false,\"isUpdatedAt\":false},{\"name\":\"contracts\",\"kind\":\"object\",\"isList\":true,\"isRequired\":true,\"isUnique\":false,\"isId\":false,\"isReadOnly\":false,\"hasDefaultValue\":false,\"type\":\"Contract\",\"relationName\":\"AddressToContract\",\"relationFromFields\":[],\"relationToFields\":[],\"isGenerated\":false,\"isUpdatedAt\":false},{\"name\":\"createdAt\",\"kind\":\"scalar\",\"isList\":false,\"isRequired\":true,\"isUnique\":false,\"isId\":false,\"isReadOnly\":false,\"hasDefaultValue\":true,\"type\":\"DateTime\",\"default\":{\"name\":\"now\",\"args\":[]},\"isGenerated\":false,\"isUpdatedAt\":false},{\"name\":\"updatedAt\",\"kind\":\"scalar\",\"isList\":false,\"isRequired\":true,\"isUnique\":false,\"isId\":false,\"isReadOnly\":false,\"hasDefaultValue\":false,\"type\":\"DateTime\",\"isGenerated\":false,\"isUpdatedAt\":true}],\"primaryKey\":null,\"uniqueFields\":[],\"uniqueIndexes\":[],\"isGenerated\":false},\"BankCard\":{\"dbName\":null,\"fields\":[{\"name\":\"id\",\"kind\":\"scalar\",\"isList\":false,\"isRequired\":true,\"isUnique\":false,\"isId\":true,\"isReadOnly\":false,\"hasDefaultValue\":true,\"type\":\"Int\",\"default\":{\"name\":\"autoincrement\",\"args\":[]},\"isGenerated\":false,\"isUpdatedAt\":false},{\"name\":\"customerId\",\"kind\":\"scalar\",\"isList\":false,\"isRequired\":true,\"isUnique\":false,\"isId\":false,\"isReadOnly\":true,\"hasDefaultValue\":false,\"type\":\"Int\",\"isGenerated\":false,\"isUpdatedAt\":false},{\"name\":\"customer\",\"kind\":\"object\",\"isList\":false,\"isRequired\":true,\"isUnique\":false,\"isId\":false,\"isReadOnly\":false,\"hasDefaultValue\":false,\"type\":\"Customer\",\"relationName\":\"BankCardToCustomer\",\"relationFromFields\":[\"customerId\"],\"relationToFields\":[\"id\"],\"relationOnDelete\":\"Cascade\",\"isGenerated\":false,\"isUpdatedAt\":false},{\"name\":\"accountHolder\",\"kind\":\"scalar\",\"isList\":false,\"isRequired\":true,\"isUnique\":false,\"isId\":false,\"isReadOnly\":false,\"hasDefaultValue\":false,\"type\":\"String\",\"isGenerated\":false,\"isUpdatedAt\":false},{\"name\":\"iban\",\"kind\":\"scalar\",\"isList\":false,\"isRequired\":true,\"isUnique\":false,\"isId\":false,\"isReadOnly\":false,\"hasDefaultValue\":false,\"type\":\"String\",\"isGenerated\":false,\"isUpdatedAt\":false},{\"name\":\"bic\",\"kind\":\"scalar\",\"isList\":false,\"isRequired\":false,\"isUnique\":false,\"isId\":false,\"isReadOnly\":false,\"hasDefaultValue\":false,\"type\":\"String\",\"isGenerated\":false,\"isUpdatedAt\":false},{\"name\":\"bankName\",\"kind\":\"scalar\",\"isList\":false,\"isRequired\":false,\"isUnique\":false,\"isId\":false,\"isReadOnly\":false,\"hasDefaultValue\":false,\"type\":\"String\",\"isGenerated\":false,\"isUpdatedAt\":false},{\"name\":\"expiryDate\",\"kind\":\"scalar\",\"isList\":false,\"isRequired\":false,\"isUnique\":false,\"isId\":false,\"isReadOnly\":false,\"hasDefaultValue\":false,\"type\":\"DateTime\",\"isGenerated\":false,\"isUpdatedAt\":false},{\"name\":\"documentPath\",\"kind\":\"scalar\",\"isList\":false,\"isRequired\":false,\"isUnique\":false,\"isId\":false,\"isReadOnly\":false,\"hasDefaultValue\":false,\"type\":\"String\",\"isGenerated\":false,\"isUpdatedAt\":false},{\"name\":\"isActive\",\"kind\":\"scalar\",\"isList\":false,\"isRequired\":true,\"isUnique\":false,\"isId\":false,\"isReadOnly\":false,\"hasDefaultValue\":true,\"type\":\"Boolean\",\"default\":true,\"isGenerated\":false,\"isUpdatedAt\":false},{\"name\":\"contracts\",\"kind\":\"object\",\"isList\":true,\"isRequired\":true,\"isUnique\":false,\"isId\":false,\"isReadOnly\":false,\"hasDefaultValue\":false,\"type\":\"Contract\",\"relationName\":\"BankCardToContract\",\"relationFromFields\":[],\"relationToFields\":[],\"isGenerated\":false,\"isUpdatedAt\":false},{\"name\":\"createdAt\",\"kind\":\"scalar\",\"isList\":false,\"isRequired\":true,\"isUnique\":false,\"isId\":false,\"isReadOnly\":false,\"hasDefaultValue\":true,\"type\":\"DateTime\",\"default\":{\"name\":\"now\",\"args\":[]},\"isGenerated\":false,\"isUpdatedAt\":false},{\"name\":\"updatedAt\",\"kind\":\"scalar\",\"isList\":false,\"isRequired\":true,\"isUnique\":false,\"isId\":false,\"isReadOnly\":false,\"hasDefaultValue\":false,\"type\":\"DateTime\",\"isGenerated\":false,\"isUpdatedAt\":true}],\"primaryKey\":null,\"uniqueFields\":[],\"uniqueIndexes\":[],\"isGenerated\":false},\"IdentityDocument\":{\"dbName\":null,\"fields\":[{\"name\":\"id\",\"kind\":\"scalar\",\"isList\":false,\"isRequired\":true,\"isUnique\":false,\"isId\":true,\"isReadOnly\":false,\"hasDefaultValue\":true,\"type\":\"Int\",\"default\":{\"name\":\"autoincrement\",\"args\":[]},\"isGenerated\":false,\"isUpdatedAt\":false},{\"name\":\"customerId\",\"kind\":\"scalar\",\"isList\":false,\"isRequired\":true,\"isUnique\":false,\"isId\":false,\"isReadOnly\":true,\"hasDefaultValue\":false,\"type\":\"Int\",\"isGenerated\":false,\"isUpdatedAt\":false},{\"name\":\"customer\",\"kind\":\"object\",\"isList\":false,\"isRequired\":true,\"isUnique\":false,\"isId\":false,\"isReadOnly\":false,\"hasDefaultValue\":false,\"type\":\"Customer\",\"relationName\":\"CustomerToIdentityDocument\",\"relationFromFields\":[\"customerId\"],\"relationToFields\":[\"id\"],\"relationOnDelete\":\"Cascade\",\"isGenerated\":false,\"isUpdatedAt\":false},{\"name\":\"type\",\"kind\":\"enum\",\"isList\":false,\"isRequired\":true,\"isUnique\":false,\"isId\":false,\"isReadOnly\":false,\"hasDefaultValue\":true,\"type\":\"DocumentType\",\"default\":\"ID_CARD\",\"isGenerated\":false,\"isUpdatedAt\":false},{\"name\":\"documentNumber\",\"kind\":\"scalar\",\"isList\":false,\"isRequired\":true,\"isUnique\":false,\"isId\":false,\"isReadOnly\":false,\"hasDefaultValue\":false,\"type\":\"String\",\"isGenerated\":false,\"isUpdatedAt\":false},{\"name\":\"issuingAuthority\",\"kind\":\"scalar\",\"isList\":false,\"isRequired\":false,\"isUnique\":false,\"isId\":false,\"isReadOnly\":false,\"hasDefaultValue\":false,\"type\":\"String\",\"isGenerated\":false,\"isUpdatedAt\":false},{\"name\":\"issueDate\",\"kind\":\"scalar\",\"isList\":false,\"isRequired\":false,\"isUnique\":false,\"isId\":false,\"isReadOnly\":false,\"hasDefaultValue\":false,\"type\":\"DateTime\",\"isGenerated\":false,\"isUpdatedAt\":false},{\"name\":\"expiryDate\",\"kind\":\"scalar\",\"isList\":false,\"isRequired\":false,\"isUnique\":false,\"isId\":false,\"isReadOnly\":false,\"hasDefaultValue\":false,\"type\":\"DateTime\",\"isGenerated\":false,\"isUpdatedAt\":false},{\"name\":\"documentPath\",\"kind\":\"scalar\",\"isList\":false,\"isRequired\":false,\"isUnique\":false,\"isId\":false,\"isReadOnly\":false,\"hasDefaultValue\":false,\"type\":\"String\",\"isGenerated\":false,\"isUpdatedAt\":false},{\"name\":\"isActive\",\"kind\":\"scalar\",\"isList\":false,\"isRequired\":true,\"isUnique\":false,\"isId\":false,\"isReadOnly\":false,\"hasDefaultValue\":true,\"type\":\"Boolean\",\"default\":true,\"isGenerated\":false,\"isUpdatedAt\":false},{\"name\":\"licenseClasses\",\"kind\":\"scalar\",\"isList\":false,\"isRequired\":false,\"isUnique\":false,\"isId\":false,\"isReadOnly\":false,\"hasDefaultValue\":false,\"type\":\"String\",\"isGenerated\":false,\"isUpdatedAt\":false},{\"name\":\"licenseIssueDate\",\"kind\":\"scalar\",\"isList\":false,\"isRequired\":false,\"isUnique\":false,\"isId\":false,\"isReadOnly\":false,\"hasDefaultValue\":false,\"type\":\"DateTime\",\"isGenerated\":false,\"isUpdatedAt\":false},{\"name\":\"contracts\",\"kind\":\"object\",\"isList\":true,\"isRequired\":true,\"isUnique\":false,\"isId\":false,\"isReadOnly\":false,\"hasDefaultValue\":false,\"type\":\"Contract\",\"relationName\":\"ContractToIdentityDocument\",\"relationFromFields\":[],\"relationToFields\":[],\"isGenerated\":false,\"isUpdatedAt\":false},{\"name\":\"createdAt\",\"kind\":\"scalar\",\"isList\":false,\"isRequired\":true,\"isUnique\":false,\"isId\":false,\"isReadOnly\":false,\"hasDefaultValue\":true,\"type\":\"DateTime\",\"default\":{\"name\":\"now\",\"args\":[]},\"isGenerated\":false,\"isUpdatedAt\":false},{\"name\":\"updatedAt\",\"kind\":\"scalar\",\"isList\":false,\"isRequired\":true,\"isUnique\":false,\"isId\":false,\"isReadOnly\":false,\"hasDefaultValue\":false,\"type\":\"DateTime\",\"isGenerated\":false,\"isUpdatedAt\":true}],\"primaryKey\":null,\"uniqueFields\":[],\"uniqueIndexes\":[],\"isGenerated\":false},\"EmailProviderConfig\":{\"dbName\":null,\"fields\":[{\"name\":\"id\",\"kind\":\"scalar\",\"isList\":false,\"isRequired\":true,\"isUnique\":false,\"isId\":true,\"isReadOnly\":false,\"hasDefaultValue\":true,\"type\":\"Int\",\"default\":{\"name\":\"autoincrement\",\"args\":[]},\"isGenerated\":false,\"isUpdatedAt\":false},{\"name\":\"name\",\"kind\":\"scalar\",\"isList\":false,\"isRequired\":true,\"isUnique\":true,\"isId\":false,\"isReadOnly\":false,\"hasDefaultValue\":false,\"type\":\"String\",\"isGenerated\":false,\"isUpdatedAt\":false},{\"name\":\"type\",\"kind\":\"enum\",\"isList\":false,\"isRequired\":true,\"isUnique\":false,\"isId\":false,\"isReadOnly\":false,\"hasDefaultValue\":false,\"type\":\"EmailProviderType\",\"isGenerated\":false,\"isUpdatedAt\":false},{\"name\":\"apiUrl\",\"kind\":\"scalar\",\"isList\":false,\"isRequired\":true,\"isUnique\":false,\"isId\":false,\"isReadOnly\":false,\"hasDefaultValue\":false,\"type\":\"String\",\"isGenerated\":false,\"isUpdatedAt\":false},{\"name\":\"apiKey\",\"kind\":\"scalar\",\"isList\":false,\"isRequired\":false,\"isUnique\":false,\"isId\":false,\"isReadOnly\":false,\"hasDefaultValue\":false,\"type\":\"String\",\"isGenerated\":false,\"isUpdatedAt\":false},{\"name\":\"username\",\"kind\":\"scalar\",\"isList\":false,\"isRequired\":false,\"isUnique\":false,\"isId\":false,\"isReadOnly\":false,\"hasDefaultValue\":false,\"type\":\"String\",\"isGenerated\":false,\"isUpdatedAt\":false},{\"name\":\"passwordEncrypted\",\"kind\":\"scalar\",\"isList\":false,\"isRequired\":false,\"isUnique\":false,\"isId\":false,\"isReadOnly\":false,\"hasDefaultValue\":false,\"type\":\"String\",\"isGenerated\":false,\"isUpdatedAt\":false},{\"name\":\"domain\",\"kind\":\"scalar\",\"isList\":false,\"isRequired\":true,\"isUnique\":false,\"isId\":false,\"isReadOnly\":false,\"hasDefaultValue\":false,\"type\":\"String\",\"isGenerated\":false,\"isUpdatedAt\":false},{\"name\":\"defaultForwardEmail\",\"kind\":\"scalar\",\"isList\":false,\"isRequired\":false,\"isUnique\":false,\"isId\":false,\"isReadOnly\":false,\"hasDefaultValue\":false,\"type\":\"String\",\"isGenerated\":false,\"isUpdatedAt\":false},{\"name\":\"imapServer\",\"kind\":\"scalar\",\"isList\":false,\"isRequired\":false,\"isUnique\":false,\"isId\":false,\"isReadOnly\":false,\"hasDefaultValue\":false,\"type\":\"String\",\"isGenerated\":false,\"isUpdatedAt\":false},{\"name\":\"imapPort\",\"kind\":\"scalar\",\"isList\":false,\"isRequired\":false,\"isUnique\":false,\"isId\":false,\"isReadOnly\":false,\"hasDefaultValue\":true,\"type\":\"Int\",\"default\":993,\"isGenerated\":false,\"isUpdatedAt\":false},{\"name\":\"smtpServer\",\"kind\":\"scalar\",\"isList\":false,\"isRequired\":false,\"isUnique\":false,\"isId\":false,\"isReadOnly\":false,\"hasDefaultValue\":false,\"type\":\"String\",\"isGenerated\":false,\"isUpdatedAt\":false},{\"name\":\"smtpPort\",\"kind\":\"scalar\",\"isList\":false,\"isRequired\":false,\"isUnique\":false,\"isId\":false,\"isReadOnly\":false,\"hasDefaultValue\":true,\"type\":\"Int\",\"default\":465,\"isGenerated\":false,\"isUpdatedAt\":false},{\"name\":\"imapEncryption\",\"kind\":\"enum\",\"isList\":false,\"isRequired\":true,\"isUnique\":false,\"isId\":false,\"isReadOnly\":false,\"hasDefaultValue\":true,\"type\":\"MailEncryption\",\"default\":\"SSL\",\"isGenerated\":false,\"isUpdatedAt\":false},{\"name\":\"smtpEncryption\",\"kind\":\"enum\",\"isList\":false,\"isRequired\":true,\"isUnique\":false,\"isId\":false,\"isReadOnly\":false,\"hasDefaultValue\":true,\"type\":\"MailEncryption\",\"default\":\"SSL\",\"isGenerated\":false,\"isUpdatedAt\":false},{\"name\":\"allowSelfSignedCerts\",\"kind\":\"scalar\",\"isList\":false,\"isRequired\":true,\"isUnique\":false,\"isId\":false,\"isReadOnly\":false,\"hasDefaultValue\":true,\"type\":\"Boolean\",\"default\":false,\"isGenerated\":false,\"isUpdatedAt\":false},{\"name\":\"isActive\",\"kind\":\"scalar\",\"isList\":false,\"isRequired\":true,\"isUnique\":false,\"isId\":false,\"isReadOnly\":false,\"hasDefaultValue\":true,\"type\":\"Boolean\",\"default\":true,\"isGenerated\":false,\"isUpdatedAt\":false},{\"name\":\"isDefault\",\"kind\":\"scalar\",\"isList\":false,\"isRequired\":true,\"isUnique\":false,\"isId\":false,\"isReadOnly\":false,\"hasDefaultValue\":true,\"type\":\"Boolean\",\"default\":false,\"isGenerated\":false,\"isUpdatedAt\":false},{\"name\":\"createdAt\",\"kind\":\"scalar\",\"isList\":false,\"isRequired\":true,\"isUnique\":false,\"isId\":false,\"isReadOnly\":false,\"hasDefaultValue\":true,\"type\":\"DateTime\",\"default\":{\"name\":\"now\",\"args\":[]},\"isGenerated\":false,\"isUpdatedAt\":false},{\"name\":\"updatedAt\",\"kind\":\"scalar\",\"isList\":false,\"isRequired\":true,\"isUnique\":false,\"isId\":false,\"isReadOnly\":false,\"hasDefaultValue\":false,\"type\":\"DateTime\",\"isGenerated\":false,\"isUpdatedAt\":true}],\"primaryKey\":null,\"uniqueFields\":[],\"uniqueIndexes\":[],\"isGenerated\":false},\"StressfreiEmail\":{\"dbName\":null,\"fields\":[{\"name\":\"id\",\"kind\":\"scalar\",\"isList\":false,\"isRequired\":true,\"isUnique\":false,\"isId\":true,\"isReadOnly\":false,\"hasDefaultValue\":true,\"type\":\"Int\",\"default\":{\"name\":\"autoincrement\",\"args\":[]},\"isGenerated\":false,\"isUpdatedAt\":false},{\"name\":\"customerId\",\"kind\":\"scalar\",\"isList\":false,\"isRequired\":true,\"isUnique\":false,\"isId\":false,\"isReadOnly\":true,\"hasDefaultValue\":false,\"type\":\"Int\",\"isGenerated\":false,\"isUpdatedAt\":false},{\"name\":\"customer\",\"kind\":\"object\",\"isList\":false,\"isRequired\":true,\"isUnique\":false,\"isId\":false,\"isReadOnly\":false,\"hasDefaultValue\":false,\"type\":\"Customer\",\"relationName\":\"CustomerToStressfreiEmail\",\"relationFromFields\":[\"customerId\"],\"relationToFields\":[\"id\"],\"relationOnDelete\":\"Cascade\",\"isGenerated\":false,\"isUpdatedAt\":false},{\"name\":\"email\",\"kind\":\"scalar\",\"isList\":false,\"isRequired\":true,\"isUnique\":false,\"isId\":false,\"isReadOnly\":false,\"hasDefaultValue\":false,\"type\":\"String\",\"isGenerated\":false,\"isUpdatedAt\":false},{\"name\":\"platform\",\"kind\":\"scalar\",\"isList\":false,\"isRequired\":false,\"isUnique\":false,\"isId\":false,\"isReadOnly\":false,\"hasDefaultValue\":false,\"type\":\"String\",\"isGenerated\":false,\"isUpdatedAt\":false},{\"name\":\"notes\",\"kind\":\"scalar\",\"isList\":false,\"isRequired\":false,\"isUnique\":false,\"isId\":false,\"isReadOnly\":false,\"hasDefaultValue\":false,\"type\":\"String\",\"isGenerated\":false,\"isUpdatedAt\":false},{\"name\":\"isActive\",\"kind\":\"scalar\",\"isList\":false,\"isRequired\":true,\"isUnique\":false,\"isId\":false,\"isReadOnly\":false,\"hasDefaultValue\":true,\"type\":\"Boolean\",\"default\":true,\"isGenerated\":false,\"isUpdatedAt\":false},{\"name\":\"isProvisioned\",\"kind\":\"scalar\",\"isList\":false,\"isRequired\":true,\"isUnique\":false,\"isId\":false,\"isReadOnly\":false,\"hasDefaultValue\":true,\"type\":\"Boolean\",\"default\":false,\"isGenerated\":false,\"isUpdatedAt\":false},{\"name\":\"provisionedAt\",\"kind\":\"scalar\",\"isList\":false,\"isRequired\":false,\"isUnique\":false,\"isId\":false,\"isReadOnly\":false,\"hasDefaultValue\":false,\"type\":\"DateTime\",\"isGenerated\":false,\"isUpdatedAt\":false},{\"name\":\"provisionError\",\"kind\":\"scalar\",\"isList\":false,\"isRequired\":false,\"isUnique\":false,\"isId\":false,\"isReadOnly\":false,\"hasDefaultValue\":false,\"type\":\"String\",\"isGenerated\":false,\"isUpdatedAt\":false},{\"name\":\"hasMailbox\",\"kind\":\"scalar\",\"isList\":false,\"isRequired\":true,\"isUnique\":false,\"isId\":false,\"isReadOnly\":false,\"hasDefaultValue\":true,\"type\":\"Boolean\",\"default\":false,\"isGenerated\":false,\"isUpdatedAt\":false},{\"name\":\"emailPasswordEncrypted\",\"kind\":\"scalar\",\"isList\":false,\"isRequired\":false,\"isUnique\":false,\"isId\":false,\"isReadOnly\":false,\"hasDefaultValue\":false,\"type\":\"String\",\"isGenerated\":false,\"isUpdatedAt\":false},{\"name\":\"contracts\",\"kind\":\"object\",\"isList\":true,\"isRequired\":true,\"isUnique\":false,\"isId\":false,\"isReadOnly\":false,\"hasDefaultValue\":false,\"type\":\"Contract\",\"relationName\":\"ContractToStressfreiEmail\",\"relationFromFields\":[],\"relationToFields\":[],\"isGenerated\":false,\"isUpdatedAt\":false},{\"name\":\"cachedEmails\",\"kind\":\"object\",\"isList\":true,\"isRequired\":true,\"isUnique\":false,\"isId\":false,\"isReadOnly\":false,\"hasDefaultValue\":false,\"type\":\"CachedEmail\",\"relationName\":\"CachedEmailToStressfreiEmail\",\"relationFromFields\":[],\"relationToFields\":[],\"isGenerated\":false,\"isUpdatedAt\":false},{\"name\":\"createdAt\",\"kind\":\"scalar\",\"isList\":false,\"isRequired\":true,\"isUnique\":false,\"isId\":false,\"isReadOnly\":false,\"hasDefaultValue\":true,\"type\":\"DateTime\",\"default\":{\"name\":\"now\",\"args\":[]},\"isGenerated\":false,\"isUpdatedAt\":false},{\"name\":\"updatedAt\",\"kind\":\"scalar\",\"isList\":false,\"isRequired\":true,\"isUnique\":false,\"isId\":false,\"isReadOnly\":false,\"hasDefaultValue\":false,\"type\":\"DateTime\",\"isGenerated\":false,\"isUpdatedAt\":true}],\"primaryKey\":null,\"uniqueFields\":[],\"uniqueIndexes\":[],\"isGenerated\":false},\"CachedEmail\":{\"dbName\":null,\"fields\":[{\"name\":\"id\",\"kind\":\"scalar\",\"isList\":false,\"isRequired\":true,\"isUnique\":false,\"isId\":true,\"isReadOnly\":false,\"hasDefaultValue\":true,\"type\":\"Int\",\"default\":{\"name\":\"autoincrement\",\"args\":[]},\"isGenerated\":false,\"isUpdatedAt\":false},{\"name\":\"stressfreiEmailId\",\"kind\":\"scalar\",\"isList\":false,\"isRequired\":true,\"isUnique\":false,\"isId\":false,\"isReadOnly\":true,\"hasDefaultValue\":false,\"type\":\"Int\",\"isGenerated\":false,\"isUpdatedAt\":false},{\"name\":\"stressfreiEmail\",\"kind\":\"object\",\"isList\":false,\"isRequired\":true,\"isUnique\":false,\"isId\":false,\"isReadOnly\":false,\"hasDefaultValue\":false,\"type\":\"StressfreiEmail\",\"relationName\":\"CachedEmailToStressfreiEmail\",\"relationFromFields\":[\"stressfreiEmailId\"],\"relationToFields\":[\"id\"],\"relationOnDelete\":\"Cascade\",\"isGenerated\":false,\"isUpdatedAt\":false},{\"name\":\"folder\",\"kind\":\"enum\",\"isList\":false,\"isRequired\":true,\"isUnique\":false,\"isId\":false,\"isReadOnly\":false,\"hasDefaultValue\":true,\"type\":\"EmailFolder\",\"default\":\"INBOX\",\"isGenerated\":false,\"isUpdatedAt\":false},{\"name\":\"messageId\",\"kind\":\"scalar\",\"isList\":false,\"isRequired\":true,\"isUnique\":false,\"isId\":false,\"isReadOnly\":false,\"hasDefaultValue\":false,\"type\":\"String\",\"isGenerated\":false,\"isUpdatedAt\":false},{\"name\":\"uid\",\"kind\":\"scalar\",\"isList\":false,\"isRequired\":true,\"isUnique\":false,\"isId\":false,\"isReadOnly\":false,\"hasDefaultValue\":false,\"type\":\"Int\",\"isGenerated\":false,\"isUpdatedAt\":false},{\"name\":\"subject\",\"kind\":\"scalar\",\"isList\":false,\"isRequired\":false,\"isUnique\":false,\"isId\":false,\"isReadOnly\":false,\"hasDefaultValue\":false,\"type\":\"String\",\"isGenerated\":false,\"isUpdatedAt\":false},{\"name\":\"fromAddress\",\"kind\":\"scalar\",\"isList\":false,\"isRequired\":true,\"isUnique\":false,\"isId\":false,\"isReadOnly\":false,\"hasDefaultValue\":false,\"type\":\"String\",\"isGenerated\":false,\"isUpdatedAt\":false},{\"name\":\"fromName\",\"kind\":\"scalar\",\"isList\":false,\"isRequired\":false,\"isUnique\":false,\"isId\":false,\"isReadOnly\":false,\"hasDefaultValue\":false,\"type\":\"String\",\"isGenerated\":false,\"isUpdatedAt\":false},{\"name\":\"toAddresses\",\"kind\":\"scalar\",\"isList\":false,\"isRequired\":true,\"isUnique\":false,\"isId\":false,\"isReadOnly\":false,\"hasDefaultValue\":false,\"type\":\"String\",\"isGenerated\":false,\"isUpdatedAt\":false},{\"name\":\"ccAddresses\",\"kind\":\"scalar\",\"isList\":false,\"isRequired\":false,\"isUnique\":false,\"isId\":false,\"isReadOnly\":false,\"hasDefaultValue\":false,\"type\":\"String\",\"isGenerated\":false,\"isUpdatedAt\":false},{\"name\":\"receivedAt\",\"kind\":\"scalar\",\"isList\":false,\"isRequired\":true,\"isUnique\":false,\"isId\":false,\"isReadOnly\":false,\"hasDefaultValue\":false,\"type\":\"DateTime\",\"isGenerated\":false,\"isUpdatedAt\":false},{\"name\":\"textBody\",\"kind\":\"scalar\",\"isList\":false,\"isRequired\":false,\"isUnique\":false,\"isId\":false,\"isReadOnly\":false,\"hasDefaultValue\":false,\"type\":\"String\",\"isGenerated\":false,\"isUpdatedAt\":false},{\"name\":\"htmlBody\",\"kind\":\"scalar\",\"isList\":false,\"isRequired\":false,\"isUnique\":false,\"isId\":false,\"isReadOnly\":false,\"hasDefaultValue\":false,\"type\":\"String\",\"isGenerated\":false,\"isUpdatedAt\":false},{\"name\":\"hasAttachments\",\"kind\":\"scalar\",\"isList\":false,\"isRequired\":true,\"isUnique\":false,\"isId\":false,\"isReadOnly\":false,\"hasDefaultValue\":true,\"type\":\"Boolean\",\"default\":false,\"isGenerated\":false,\"isUpdatedAt\":false},{\"name\":\"attachmentNames\",\"kind\":\"scalar\",\"isList\":false,\"isRequired\":false,\"isUnique\":false,\"isId\":false,\"isReadOnly\":false,\"hasDefaultValue\":false,\"type\":\"String\",\"isGenerated\":false,\"isUpdatedAt\":false},{\"name\":\"contractId\",\"kind\":\"scalar\",\"isList\":false,\"isRequired\":false,\"isUnique\":false,\"isId\":false,\"isReadOnly\":true,\"hasDefaultValue\":false,\"type\":\"Int\",\"isGenerated\":false,\"isUpdatedAt\":false},{\"name\":\"contract\",\"kind\":\"object\",\"isList\":false,\"isRequired\":false,\"isUnique\":false,\"isId\":false,\"isReadOnly\":false,\"hasDefaultValue\":false,\"type\":\"Contract\",\"relationName\":\"CachedEmailToContract\",\"relationFromFields\":[\"contractId\"],\"relationToFields\":[\"id\"],\"relationOnDelete\":\"SetNull\",\"isGenerated\":false,\"isUpdatedAt\":false},{\"name\":\"assignedAt\",\"kind\":\"scalar\",\"isList\":false,\"isRequired\":false,\"isUnique\":false,\"isId\":false,\"isReadOnly\":false,\"hasDefaultValue\":false,\"type\":\"DateTime\",\"isGenerated\":false,\"isUpdatedAt\":false},{\"name\":\"assignedBy\",\"kind\":\"scalar\",\"isList\":false,\"isRequired\":false,\"isUnique\":false,\"isId\":false,\"isReadOnly\":false,\"hasDefaultValue\":false,\"type\":\"Int\",\"isGenerated\":false,\"isUpdatedAt\":false},{\"name\":\"isAutoAssigned\",\"kind\":\"scalar\",\"isList\":false,\"isRequired\":true,\"isUnique\":false,\"isId\":false,\"isReadOnly\":false,\"hasDefaultValue\":true,\"type\":\"Boolean\",\"default\":false,\"isGenerated\":false,\"isUpdatedAt\":false},{\"name\":\"isRead\",\"kind\":\"scalar\",\"isList\":false,\"isRequired\":true,\"isUnique\":false,\"isId\":false,\"isReadOnly\":false,\"hasDefaultValue\":true,\"type\":\"Boolean\",\"default\":false,\"isGenerated\":false,\"isUpdatedAt\":false},{\"name\":\"isStarred\",\"kind\":\"scalar\",\"isList\":false,\"isRequired\":true,\"isUnique\":false,\"isId\":false,\"isReadOnly\":false,\"hasDefaultValue\":true,\"type\":\"Boolean\",\"default\":false,\"isGenerated\":false,\"isUpdatedAt\":false},{\"name\":\"isDeleted\",\"kind\":\"scalar\",\"isList\":false,\"isRequired\":true,\"isUnique\":false,\"isId\":false,\"isReadOnly\":false,\"hasDefaultValue\":true,\"type\":\"Boolean\",\"default\":false,\"isGenerated\":false,\"isUpdatedAt\":false},{\"name\":\"deletedAt\",\"kind\":\"scalar\",\"isList\":false,\"isRequired\":false,\"isUnique\":false,\"isId\":false,\"isReadOnly\":false,\"hasDefaultValue\":false,\"type\":\"DateTime\",\"isGenerated\":false,\"isUpdatedAt\":false},{\"name\":\"createdAt\",\"kind\":\"scalar\",\"isList\":false,\"isRequired\":true,\"isUnique\":false,\"isId\":false,\"isReadOnly\":false,\"hasDefaultValue\":true,\"type\":\"DateTime\",\"default\":{\"name\":\"now\",\"args\":[]},\"isGenerated\":false,\"isUpdatedAt\":false},{\"name\":\"updatedAt\",\"kind\":\"scalar\",\"isList\":false,\"isRequired\":true,\"isUnique\":false,\"isId\":false,\"isReadOnly\":false,\"hasDefaultValue\":false,\"type\":\"DateTime\",\"isGenerated\":false,\"isUpdatedAt\":true}],\"primaryKey\":null,\"uniqueFields\":[[\"stressfreiEmailId\",\"messageId\",\"folder\"]],\"uniqueIndexes\":[{\"name\":null,\"fields\":[\"stressfreiEmailId\",\"messageId\",\"folder\"]}],\"isGenerated\":false},\"Meter\":{\"dbName\":null,\"fields\":[{\"name\":\"id\",\"kind\":\"scalar\",\"isList\":false,\"isRequired\":true,\"isUnique\":false,\"isId\":true,\"isReadOnly\":false,\"hasDefaultValue\":true,\"type\":\"Int\",\"default\":{\"name\":\"autoincrement\",\"args\":[]},\"isGenerated\":false,\"isUpdatedAt\":false},{\"name\":\"customerId\",\"kind\":\"scalar\",\"isList\":false,\"isRequired\":true,\"isUnique\":false,\"isId\":false,\"isReadOnly\":true,\"hasDefaultValue\":false,\"type\":\"Int\",\"isGenerated\":false,\"isUpdatedAt\":false},{\"name\":\"customer\",\"kind\":\"object\",\"isList\":false,\"isRequired\":true,\"isUnique\":false,\"isId\":false,\"isReadOnly\":false,\"hasDefaultValue\":false,\"type\":\"Customer\",\"relationName\":\"CustomerToMeter\",\"relationFromFields\":[\"customerId\"],\"relationToFields\":[\"id\"],\"relationOnDelete\":\"Cascade\",\"isGenerated\":false,\"isUpdatedAt\":false},{\"name\":\"meterNumber\",\"kind\":\"scalar\",\"isList\":false,\"isRequired\":true,\"isUnique\":false,\"isId\":false,\"isReadOnly\":false,\"hasDefaultValue\":false,\"type\":\"String\",\"isGenerated\":false,\"isUpdatedAt\":false},{\"name\":\"type\",\"kind\":\"enum\",\"isList\":false,\"isRequired\":true,\"isUnique\":false,\"isId\":false,\"isReadOnly\":false,\"hasDefaultValue\":false,\"type\":\"MeterType\",\"isGenerated\":false,\"isUpdatedAt\":false},{\"name\":\"location\",\"kind\":\"scalar\",\"isList\":false,\"isRequired\":false,\"isUnique\":false,\"isId\":false,\"isReadOnly\":false,\"hasDefaultValue\":false,\"type\":\"String\",\"isGenerated\":false,\"isUpdatedAt\":false},{\"name\":\"isActive\",\"kind\":\"scalar\",\"isList\":false,\"isRequired\":true,\"isUnique\":false,\"isId\":false,\"isReadOnly\":false,\"hasDefaultValue\":true,\"type\":\"Boolean\",\"default\":true,\"isGenerated\":false,\"isUpdatedAt\":false},{\"name\":\"readings\",\"kind\":\"object\",\"isList\":true,\"isRequired\":true,\"isUnique\":false,\"isId\":false,\"isReadOnly\":false,\"hasDefaultValue\":false,\"type\":\"MeterReading\",\"relationName\":\"MeterToMeterReading\",\"relationFromFields\":[],\"relationToFields\":[],\"isGenerated\":false,\"isUpdatedAt\":false},{\"name\":\"energyDetails\",\"kind\":\"object\",\"isList\":true,\"isRequired\":true,\"isUnique\":false,\"isId\":false,\"isReadOnly\":false,\"hasDefaultValue\":false,\"type\":\"EnergyContractDetails\",\"relationName\":\"EnergyContractDetailsToMeter\",\"relationFromFields\":[],\"relationToFields\":[],\"isGenerated\":false,\"isUpdatedAt\":false},{\"name\":\"createdAt\",\"kind\":\"scalar\",\"isList\":false,\"isRequired\":true,\"isUnique\":false,\"isId\":false,\"isReadOnly\":false,\"hasDefaultValue\":true,\"type\":\"DateTime\",\"default\":{\"name\":\"now\",\"args\":[]},\"isGenerated\":false,\"isUpdatedAt\":false},{\"name\":\"updatedAt\",\"kind\":\"scalar\",\"isList\":false,\"isRequired\":true,\"isUnique\":false,\"isId\":false,\"isReadOnly\":false,\"hasDefaultValue\":false,\"type\":\"DateTime\",\"isGenerated\":false,\"isUpdatedAt\":true}],\"primaryKey\":null,\"uniqueFields\":[],\"uniqueIndexes\":[],\"isGenerated\":false},\"MeterReading\":{\"dbName\":null,\"fields\":[{\"name\":\"id\",\"kind\":\"scalar\",\"isList\":false,\"isRequired\":true,\"isUnique\":false,\"isId\":true,\"isReadOnly\":false,\"hasDefaultValue\":true,\"type\":\"Int\",\"default\":{\"name\":\"autoincrement\",\"args\":[]},\"isGenerated\":false,\"isUpdatedAt\":false},{\"name\":\"meterId\",\"kind\":\"scalar\",\"isList\":false,\"isRequired\":true,\"isUnique\":false,\"isId\":false,\"isReadOnly\":true,\"hasDefaultValue\":false,\"type\":\"Int\",\"isGenerated\":false,\"isUpdatedAt\":false},{\"name\":\"meter\",\"kind\":\"object\",\"isList\":false,\"isRequired\":true,\"isUnique\":false,\"isId\":false,\"isReadOnly\":false,\"hasDefaultValue\":false,\"type\":\"Meter\",\"relationName\":\"MeterToMeterReading\",\"relationFromFields\":[\"meterId\"],\"relationToFields\":[\"id\"],\"relationOnDelete\":\"Cascade\",\"isGenerated\":false,\"isUpdatedAt\":false},{\"name\":\"readingDate\",\"kind\":\"scalar\",\"isList\":false,\"isRequired\":true,\"isUnique\":false,\"isId\":false,\"isReadOnly\":false,\"hasDefaultValue\":false,\"type\":\"DateTime\",\"isGenerated\":false,\"isUpdatedAt\":false},{\"name\":\"value\",\"kind\":\"scalar\",\"isList\":false,\"isRequired\":true,\"isUnique\":false,\"isId\":false,\"isReadOnly\":false,\"hasDefaultValue\":false,\"type\":\"Float\",\"isGenerated\":false,\"isUpdatedAt\":false},{\"name\":\"unit\",\"kind\":\"scalar\",\"isList\":false,\"isRequired\":true,\"isUnique\":false,\"isId\":false,\"isReadOnly\":false,\"hasDefaultValue\":true,\"type\":\"String\",\"default\":\"kWh\",\"isGenerated\":false,\"isUpdatedAt\":false},{\"name\":\"notes\",\"kind\":\"scalar\",\"isList\":false,\"isRequired\":false,\"isUnique\":false,\"isId\":false,\"isReadOnly\":false,\"hasDefaultValue\":false,\"type\":\"String\",\"isGenerated\":false,\"isUpdatedAt\":false},{\"name\":\"createdAt\",\"kind\":\"scalar\",\"isList\":false,\"isRequired\":true,\"isUnique\":false,\"isId\":false,\"isReadOnly\":false,\"hasDefaultValue\":true,\"type\":\"DateTime\",\"default\":{\"name\":\"now\",\"args\":[]},\"isGenerated\":false,\"isUpdatedAt\":false}],\"primaryKey\":null,\"uniqueFields\":[],\"uniqueIndexes\":[],\"isGenerated\":false},\"SalesPlatform\":{\"dbName\":null,\"fields\":[{\"name\":\"id\",\"kind\":\"scalar\",\"isList\":false,\"isRequired\":true,\"isUnique\":false,\"isId\":true,\"isReadOnly\":false,\"hasDefaultValue\":true,\"type\":\"Int\",\"default\":{\"name\":\"autoincrement\",\"args\":[]},\"isGenerated\":false,\"isUpdatedAt\":false},{\"name\":\"name\",\"kind\":\"scalar\",\"isList\":false,\"isRequired\":true,\"isUnique\":true,\"isId\":false,\"isReadOnly\":false,\"hasDefaultValue\":false,\"type\":\"String\",\"isGenerated\":false,\"isUpdatedAt\":false},{\"name\":\"contactInfo\",\"kind\":\"scalar\",\"isList\":false,\"isRequired\":false,\"isUnique\":false,\"isId\":false,\"isReadOnly\":false,\"hasDefaultValue\":false,\"type\":\"String\",\"isGenerated\":false,\"isUpdatedAt\":false},{\"name\":\"isActive\",\"kind\":\"scalar\",\"isList\":false,\"isRequired\":true,\"isUnique\":false,\"isId\":false,\"isReadOnly\":false,\"hasDefaultValue\":true,\"type\":\"Boolean\",\"default\":true,\"isGenerated\":false,\"isUpdatedAt\":false},{\"name\":\"contracts\",\"kind\":\"object\",\"isList\":true,\"isRequired\":true,\"isUnique\":false,\"isId\":false,\"isReadOnly\":false,\"hasDefaultValue\":false,\"type\":\"Contract\",\"relationName\":\"ContractToSalesPlatform\",\"relationFromFields\":[],\"relationToFields\":[],\"isGenerated\":false,\"isUpdatedAt\":false},{\"name\":\"createdAt\",\"kind\":\"scalar\",\"isList\":false,\"isRequired\":true,\"isUnique\":false,\"isId\":false,\"isReadOnly\":false,\"hasDefaultValue\":true,\"type\":\"DateTime\",\"default\":{\"name\":\"now\",\"args\":[]},\"isGenerated\":false,\"isUpdatedAt\":false},{\"name\":\"updatedAt\",\"kind\":\"scalar\",\"isList\":false,\"isRequired\":true,\"isUnique\":false,\"isId\":false,\"isReadOnly\":false,\"hasDefaultValue\":false,\"type\":\"DateTime\",\"isGenerated\":false,\"isUpdatedAt\":true}],\"primaryKey\":null,\"uniqueFields\":[],\"uniqueIndexes\":[],\"isGenerated\":false},\"CancellationPeriod\":{\"dbName\":null,\"fields\":[{\"name\":\"id\",\"kind\":\"scalar\",\"isList\":false,\"isRequired\":true,\"isUnique\":false,\"isId\":true,\"isReadOnly\":false,\"hasDefaultValue\":true,\"type\":\"Int\",\"default\":{\"name\":\"autoincrement\",\"args\":[]},\"isGenerated\":false,\"isUpdatedAt\":false},{\"name\":\"code\",\"kind\":\"scalar\",\"isList\":false,\"isRequired\":true,\"isUnique\":true,\"isId\":false,\"isReadOnly\":false,\"hasDefaultValue\":false,\"type\":\"String\",\"isGenerated\":false,\"isUpdatedAt\":false},{\"name\":\"description\",\"kind\":\"scalar\",\"isList\":false,\"isRequired\":true,\"isUnique\":false,\"isId\":false,\"isReadOnly\":false,\"hasDefaultValue\":false,\"type\":\"String\",\"isGenerated\":false,\"isUpdatedAt\":false},{\"name\":\"isActive\",\"kind\":\"scalar\",\"isList\":false,\"isRequired\":true,\"isUnique\":false,\"isId\":false,\"isReadOnly\":false,\"hasDefaultValue\":true,\"type\":\"Boolean\",\"default\":true,\"isGenerated\":false,\"isUpdatedAt\":false},{\"name\":\"contracts\",\"kind\":\"object\",\"isList\":true,\"isRequired\":true,\"isUnique\":false,\"isId\":false,\"isReadOnly\":false,\"hasDefaultValue\":false,\"type\":\"Contract\",\"relationName\":\"CancellationPeriodToContract\",\"relationFromFields\":[],\"relationToFields\":[],\"isGenerated\":false,\"isUpdatedAt\":false},{\"name\":\"createdAt\",\"kind\":\"scalar\",\"isList\":false,\"isRequired\":true,\"isUnique\":false,\"isId\":false,\"isReadOnly\":false,\"hasDefaultValue\":true,\"type\":\"DateTime\",\"default\":{\"name\":\"now\",\"args\":[]},\"isGenerated\":false,\"isUpdatedAt\":false},{\"name\":\"updatedAt\",\"kind\":\"scalar\",\"isList\":false,\"isRequired\":true,\"isUnique\":false,\"isId\":false,\"isReadOnly\":false,\"hasDefaultValue\":false,\"type\":\"DateTime\",\"isGenerated\":false,\"isUpdatedAt\":true}],\"primaryKey\":null,\"uniqueFields\":[],\"uniqueIndexes\":[],\"isGenerated\":false},\"ContractDuration\":{\"dbName\":null,\"fields\":[{\"name\":\"id\",\"kind\":\"scalar\",\"isList\":false,\"isRequired\":true,\"isUnique\":false,\"isId\":true,\"isReadOnly\":false,\"hasDefaultValue\":true,\"type\":\"Int\",\"default\":{\"name\":\"autoincrement\",\"args\":[]},\"isGenerated\":false,\"isUpdatedAt\":false},{\"name\":\"code\",\"kind\":\"scalar\",\"isList\":false,\"isRequired\":true,\"isUnique\":true,\"isId\":false,\"isReadOnly\":false,\"hasDefaultValue\":false,\"type\":\"String\",\"isGenerated\":false,\"isUpdatedAt\":false},{\"name\":\"description\",\"kind\":\"scalar\",\"isList\":false,\"isRequired\":true,\"isUnique\":false,\"isId\":false,\"isReadOnly\":false,\"hasDefaultValue\":false,\"type\":\"String\",\"isGenerated\":false,\"isUpdatedAt\":false},{\"name\":\"isActive\",\"kind\":\"scalar\",\"isList\":false,\"isRequired\":true,\"isUnique\":false,\"isId\":false,\"isReadOnly\":false,\"hasDefaultValue\":true,\"type\":\"Boolean\",\"default\":true,\"isGenerated\":false,\"isUpdatedAt\":false},{\"name\":\"contracts\",\"kind\":\"object\",\"isList\":true,\"isRequired\":true,\"isUnique\":false,\"isId\":false,\"isReadOnly\":false,\"hasDefaultValue\":false,\"type\":\"Contract\",\"relationName\":\"ContractToContractDuration\",\"relationFromFields\":[],\"relationToFields\":[],\"isGenerated\":false,\"isUpdatedAt\":false},{\"name\":\"createdAt\",\"kind\":\"scalar\",\"isList\":false,\"isRequired\":true,\"isUnique\":false,\"isId\":false,\"isReadOnly\":false,\"hasDefaultValue\":true,\"type\":\"DateTime\",\"default\":{\"name\":\"now\",\"args\":[]},\"isGenerated\":false,\"isUpdatedAt\":false},{\"name\":\"updatedAt\",\"kind\":\"scalar\",\"isList\":false,\"isRequired\":true,\"isUnique\":false,\"isId\":false,\"isReadOnly\":false,\"hasDefaultValue\":false,\"type\":\"DateTime\",\"isGenerated\":false,\"isUpdatedAt\":true}],\"primaryKey\":null,\"uniqueFields\":[],\"uniqueIndexes\":[],\"isGenerated\":false},\"Provider\":{\"dbName\":null,\"fields\":[{\"name\":\"id\",\"kind\":\"scalar\",\"isList\":false,\"isRequired\":true,\"isUnique\":false,\"isId\":true,\"isReadOnly\":false,\"hasDefaultValue\":true,\"type\":\"Int\",\"default\":{\"name\":\"autoincrement\",\"args\":[]},\"isGenerated\":false,\"isUpdatedAt\":false},{\"name\":\"name\",\"kind\":\"scalar\",\"isList\":false,\"isRequired\":true,\"isUnique\":true,\"isId\":false,\"isReadOnly\":false,\"hasDefaultValue\":false,\"type\":\"String\",\"isGenerated\":false,\"isUpdatedAt\":false},{\"name\":\"portalUrl\",\"kind\":\"scalar\",\"isList\":false,\"isRequired\":false,\"isUnique\":false,\"isId\":false,\"isReadOnly\":false,\"hasDefaultValue\":false,\"type\":\"String\",\"isGenerated\":false,\"isUpdatedAt\":false},{\"name\":\"usernameFieldName\",\"kind\":\"scalar\",\"isList\":false,\"isRequired\":false,\"isUnique\":false,\"isId\":false,\"isReadOnly\":false,\"hasDefaultValue\":false,\"type\":\"String\",\"isGenerated\":false,\"isUpdatedAt\":false},{\"name\":\"passwordFieldName\",\"kind\":\"scalar\",\"isList\":false,\"isRequired\":false,\"isUnique\":false,\"isId\":false,\"isReadOnly\":false,\"hasDefaultValue\":false,\"type\":\"String\",\"isGenerated\":false,\"isUpdatedAt\":false},{\"name\":\"isActive\",\"kind\":\"scalar\",\"isList\":false,\"isRequired\":true,\"isUnique\":false,\"isId\":false,\"isReadOnly\":false,\"hasDefaultValue\":true,\"type\":\"Boolean\",\"default\":true,\"isGenerated\":false,\"isUpdatedAt\":false},{\"name\":\"tariffs\",\"kind\":\"object\",\"isList\":true,\"isRequired\":true,\"isUnique\":false,\"isId\":false,\"isReadOnly\":false,\"hasDefaultValue\":false,\"type\":\"Tariff\",\"relationName\":\"ProviderToTariff\",\"relationFromFields\":[],\"relationToFields\":[],\"isGenerated\":false,\"isUpdatedAt\":false},{\"name\":\"contracts\",\"kind\":\"object\",\"isList\":true,\"isRequired\":true,\"isUnique\":false,\"isId\":false,\"isReadOnly\":false,\"hasDefaultValue\":false,\"type\":\"Contract\",\"relationName\":\"ContractToProvider\",\"relationFromFields\":[],\"relationToFields\":[],\"isGenerated\":false,\"isUpdatedAt\":false},{\"name\":\"createdAt\",\"kind\":\"scalar\",\"isList\":false,\"isRequired\":true,\"isUnique\":false,\"isId\":false,\"isReadOnly\":false,\"hasDefaultValue\":true,\"type\":\"DateTime\",\"default\":{\"name\":\"now\",\"args\":[]},\"isGenerated\":false,\"isUpdatedAt\":false},{\"name\":\"updatedAt\",\"kind\":\"scalar\",\"isList\":false,\"isRequired\":true,\"isUnique\":false,\"isId\":false,\"isReadOnly\":false,\"hasDefaultValue\":false,\"type\":\"DateTime\",\"isGenerated\":false,\"isUpdatedAt\":true}],\"primaryKey\":null,\"uniqueFields\":[],\"uniqueIndexes\":[],\"isGenerated\":false},\"Tariff\":{\"dbName\":null,\"fields\":[{\"name\":\"id\",\"kind\":\"scalar\",\"isList\":false,\"isRequired\":true,\"isUnique\":false,\"isId\":true,\"isReadOnly\":false,\"hasDefaultValue\":true,\"type\":\"Int\",\"default\":{\"name\":\"autoincrement\",\"args\":[]},\"isGenerated\":false,\"isUpdatedAt\":false},{\"name\":\"providerId\",\"kind\":\"scalar\",\"isList\":false,\"isRequired\":true,\"isUnique\":false,\"isId\":false,\"isReadOnly\":true,\"hasDefaultValue\":false,\"type\":\"Int\",\"isGenerated\":false,\"isUpdatedAt\":false},{\"name\":\"provider\",\"kind\":\"object\",\"isList\":false,\"isRequired\":true,\"isUnique\":false,\"isId\":false,\"isReadOnly\":false,\"hasDefaultValue\":false,\"type\":\"Provider\",\"relationName\":\"ProviderToTariff\",\"relationFromFields\":[\"providerId\"],\"relationToFields\":[\"id\"],\"relationOnDelete\":\"Cascade\",\"isGenerated\":false,\"isUpdatedAt\":false},{\"name\":\"name\",\"kind\":\"scalar\",\"isList\":false,\"isRequired\":true,\"isUnique\":false,\"isId\":false,\"isReadOnly\":false,\"hasDefaultValue\":false,\"type\":\"String\",\"isGenerated\":false,\"isUpdatedAt\":false},{\"name\":\"isActive\",\"kind\":\"scalar\",\"isList\":false,\"isRequired\":true,\"isUnique\":false,\"isId\":false,\"isReadOnly\":false,\"hasDefaultValue\":true,\"type\":\"Boolean\",\"default\":true,\"isGenerated\":false,\"isUpdatedAt\":false},{\"name\":\"contracts\",\"kind\":\"object\",\"isList\":true,\"isRequired\":true,\"isUnique\":false,\"isId\":false,\"isReadOnly\":false,\"hasDefaultValue\":false,\"type\":\"Contract\",\"relationName\":\"ContractToTariff\",\"relationFromFields\":[],\"relationToFields\":[],\"isGenerated\":false,\"isUpdatedAt\":false},{\"name\":\"createdAt\",\"kind\":\"scalar\",\"isList\":false,\"isRequired\":true,\"isUnique\":false,\"isId\":false,\"isReadOnly\":false,\"hasDefaultValue\":true,\"type\":\"DateTime\",\"default\":{\"name\":\"now\",\"args\":[]},\"isGenerated\":false,\"isUpdatedAt\":false},{\"name\":\"updatedAt\",\"kind\":\"scalar\",\"isList\":false,\"isRequired\":true,\"isUnique\":false,\"isId\":false,\"isReadOnly\":false,\"hasDefaultValue\":false,\"type\":\"DateTime\",\"isGenerated\":false,\"isUpdatedAt\":true}],\"primaryKey\":null,\"uniqueFields\":[[\"providerId\",\"name\"]],\"uniqueIndexes\":[{\"name\":null,\"fields\":[\"providerId\",\"name\"]}],\"isGenerated\":false},\"ContractCategory\":{\"dbName\":null,\"fields\":[{\"name\":\"id\",\"kind\":\"scalar\",\"isList\":false,\"isRequired\":true,\"isUnique\":false,\"isId\":true,\"isReadOnly\":false,\"hasDefaultValue\":true,\"type\":\"Int\",\"default\":{\"name\":\"autoincrement\",\"args\":[]},\"isGenerated\":false,\"isUpdatedAt\":false},{\"name\":\"code\",\"kind\":\"scalar\",\"isList\":false,\"isRequired\":true,\"isUnique\":true,\"isId\":false,\"isReadOnly\":false,\"hasDefaultValue\":false,\"type\":\"String\",\"isGenerated\":false,\"isUpdatedAt\":false},{\"name\":\"name\",\"kind\":\"scalar\",\"isList\":false,\"isRequired\":true,\"isUnique\":false,\"isId\":false,\"isReadOnly\":false,\"hasDefaultValue\":false,\"type\":\"String\",\"isGenerated\":false,\"isUpdatedAt\":false},{\"name\":\"icon\",\"kind\":\"scalar\",\"isList\":false,\"isRequired\":false,\"isUnique\":false,\"isId\":false,\"isReadOnly\":false,\"hasDefaultValue\":false,\"type\":\"String\",\"isGenerated\":false,\"isUpdatedAt\":false},{\"name\":\"color\",\"kind\":\"scalar\",\"isList\":false,\"isRequired\":false,\"isUnique\":false,\"isId\":false,\"isReadOnly\":false,\"hasDefaultValue\":false,\"type\":\"String\",\"isGenerated\":false,\"isUpdatedAt\":false},{\"name\":\"sortOrder\",\"kind\":\"scalar\",\"isList\":false,\"isRequired\":true,\"isUnique\":false,\"isId\":false,\"isReadOnly\":false,\"hasDefaultValue\":true,\"type\":\"Int\",\"default\":0,\"isGenerated\":false,\"isUpdatedAt\":false},{\"name\":\"isActive\",\"kind\":\"scalar\",\"isList\":false,\"isRequired\":true,\"isUnique\":false,\"isId\":false,\"isReadOnly\":false,\"hasDefaultValue\":true,\"type\":\"Boolean\",\"default\":true,\"isGenerated\":false,\"isUpdatedAt\":false},{\"name\":\"contracts\",\"kind\":\"object\",\"isList\":true,\"isRequired\":true,\"isUnique\":false,\"isId\":false,\"isReadOnly\":false,\"hasDefaultValue\":false,\"type\":\"Contract\",\"relationName\":\"ContractToContractCategory\",\"relationFromFields\":[],\"relationToFields\":[],\"isGenerated\":false,\"isUpdatedAt\":false},{\"name\":\"createdAt\",\"kind\":\"scalar\",\"isList\":false,\"isRequired\":true,\"isUnique\":false,\"isId\":false,\"isReadOnly\":false,\"hasDefaultValue\":true,\"type\":\"DateTime\",\"default\":{\"name\":\"now\",\"args\":[]},\"isGenerated\":false,\"isUpdatedAt\":false},{\"name\":\"updatedAt\",\"kind\":\"scalar\",\"isList\":false,\"isRequired\":true,\"isUnique\":false,\"isId\":false,\"isReadOnly\":false,\"hasDefaultValue\":false,\"type\":\"DateTime\",\"isGenerated\":false,\"isUpdatedAt\":true}],\"primaryKey\":null,\"uniqueFields\":[],\"uniqueIndexes\":[],\"isGenerated\":false},\"Contract\":{\"dbName\":null,\"fields\":[{\"name\":\"id\",\"kind\":\"scalar\",\"isList\":false,\"isRequired\":true,\"isUnique\":false,\"isId\":true,\"isReadOnly\":false,\"hasDefaultValue\":true,\"type\":\"Int\",\"default\":{\"name\":\"autoincrement\",\"args\":[]},\"isGenerated\":false,\"isUpdatedAt\":false},{\"name\":\"contractNumber\",\"kind\":\"scalar\",\"isList\":false,\"isRequired\":true,\"isUnique\":true,\"isId\":false,\"isReadOnly\":false,\"hasDefaultValue\":false,\"type\":\"String\",\"isGenerated\":false,\"isUpdatedAt\":false},{\"name\":\"customerId\",\"kind\":\"scalar\",\"isList\":false,\"isRequired\":true,\"isUnique\":false,\"isId\":false,\"isReadOnly\":true,\"hasDefaultValue\":false,\"type\":\"Int\",\"isGenerated\":false,\"isUpdatedAt\":false},{\"name\":\"customer\",\"kind\":\"object\",\"isList\":false,\"isRequired\":true,\"isUnique\":false,\"isId\":false,\"isReadOnly\":false,\"hasDefaultValue\":false,\"type\":\"Customer\",\"relationName\":\"ContractToCustomer\",\"relationFromFields\":[\"customerId\"],\"relationToFields\":[\"id\"],\"relationOnDelete\":\"Cascade\",\"isGenerated\":false,\"isUpdatedAt\":false},{\"name\":\"type\",\"kind\":\"enum\",\"isList\":false,\"isRequired\":true,\"isUnique\":false,\"isId\":false,\"isReadOnly\":false,\"hasDefaultValue\":false,\"type\":\"ContractType\",\"isGenerated\":false,\"isUpdatedAt\":false},{\"name\":\"status\",\"kind\":\"enum\",\"isList\":false,\"isRequired\":true,\"isUnique\":false,\"isId\":false,\"isReadOnly\":false,\"hasDefaultValue\":true,\"type\":\"ContractStatus\",\"default\":\"DRAFT\",\"isGenerated\":false,\"isUpdatedAt\":false},{\"name\":\"contractCategoryId\",\"kind\":\"scalar\",\"isList\":false,\"isRequired\":false,\"isUnique\":false,\"isId\":false,\"isReadOnly\":true,\"hasDefaultValue\":false,\"type\":\"Int\",\"isGenerated\":false,\"isUpdatedAt\":false},{\"name\":\"contractCategory\",\"kind\":\"object\",\"isList\":false,\"isRequired\":false,\"isUnique\":false,\"isId\":false,\"isReadOnly\":false,\"hasDefaultValue\":false,\"type\":\"ContractCategory\",\"relationName\":\"ContractToContractCategory\",\"relationFromFields\":[\"contractCategoryId\"],\"relationToFields\":[\"id\"],\"isGenerated\":false,\"isUpdatedAt\":false},{\"name\":\"addressId\",\"kind\":\"scalar\",\"isList\":false,\"isRequired\":false,\"isUnique\":false,\"isId\":false,\"isReadOnly\":true,\"hasDefaultValue\":false,\"type\":\"Int\",\"isGenerated\":false,\"isUpdatedAt\":false},{\"name\":\"address\",\"kind\":\"object\",\"isList\":false,\"isRequired\":false,\"isUnique\":false,\"isId\":false,\"isReadOnly\":false,\"hasDefaultValue\":false,\"type\":\"Address\",\"relationName\":\"AddressToContract\",\"relationFromFields\":[\"addressId\"],\"relationToFields\":[\"id\"],\"isGenerated\":false,\"isUpdatedAt\":false},{\"name\":\"bankCardId\",\"kind\":\"scalar\",\"isList\":false,\"isRequired\":false,\"isUnique\":false,\"isId\":false,\"isReadOnly\":true,\"hasDefaultValue\":false,\"type\":\"Int\",\"isGenerated\":false,\"isUpdatedAt\":false},{\"name\":\"bankCard\",\"kind\":\"object\",\"isList\":false,\"isRequired\":false,\"isUnique\":false,\"isId\":false,\"isReadOnly\":false,\"hasDefaultValue\":false,\"type\":\"BankCard\",\"relationName\":\"BankCardToContract\",\"relationFromFields\":[\"bankCardId\"],\"relationToFields\":[\"id\"],\"isGenerated\":false,\"isUpdatedAt\":false},{\"name\":\"identityDocumentId\",\"kind\":\"scalar\",\"isList\":false,\"isRequired\":false,\"isUnique\":false,\"isId\":false,\"isReadOnly\":true,\"hasDefaultValue\":false,\"type\":\"Int\",\"isGenerated\":false,\"isUpdatedAt\":false},{\"name\":\"identityDocument\",\"kind\":\"object\",\"isList\":false,\"isRequired\":false,\"isUnique\":false,\"isId\":false,\"isReadOnly\":false,\"hasDefaultValue\":false,\"type\":\"IdentityDocument\",\"relationName\":\"ContractToIdentityDocument\",\"relationFromFields\":[\"identityDocumentId\"],\"relationToFields\":[\"id\"],\"isGenerated\":false,\"isUpdatedAt\":false},{\"name\":\"salesPlatformId\",\"kind\":\"scalar\",\"isList\":false,\"isRequired\":false,\"isUnique\":false,\"isId\":false,\"isReadOnly\":true,\"hasDefaultValue\":false,\"type\":\"Int\",\"isGenerated\":false,\"isUpdatedAt\":false},{\"name\":\"salesPlatform\",\"kind\":\"object\",\"isList\":false,\"isRequired\":false,\"isUnique\":false,\"isId\":false,\"isReadOnly\":false,\"hasDefaultValue\":false,\"type\":\"SalesPlatform\",\"relationName\":\"ContractToSalesPlatform\",\"relationFromFields\":[\"salesPlatformId\"],\"relationToFields\":[\"id\"],\"isGenerated\":false,\"isUpdatedAt\":false},{\"name\":\"cancellationPeriodId\",\"kind\":\"scalar\",\"isList\":false,\"isRequired\":false,\"isUnique\":false,\"isId\":false,\"isReadOnly\":true,\"hasDefaultValue\":false,\"type\":\"Int\",\"isGenerated\":false,\"isUpdatedAt\":false},{\"name\":\"cancellationPeriod\",\"kind\":\"object\",\"isList\":false,\"isRequired\":false,\"isUnique\":false,\"isId\":false,\"isReadOnly\":false,\"hasDefaultValue\":false,\"type\":\"CancellationPeriod\",\"relationName\":\"CancellationPeriodToContract\",\"relationFromFields\":[\"cancellationPeriodId\"],\"relationToFields\":[\"id\"],\"isGenerated\":false,\"isUpdatedAt\":false},{\"name\":\"contractDurationId\",\"kind\":\"scalar\",\"isList\":false,\"isRequired\":false,\"isUnique\":false,\"isId\":false,\"isReadOnly\":true,\"hasDefaultValue\":false,\"type\":\"Int\",\"isGenerated\":false,\"isUpdatedAt\":false},{\"name\":\"contractDuration\",\"kind\":\"object\",\"isList\":false,\"isRequired\":false,\"isUnique\":false,\"isId\":false,\"isReadOnly\":false,\"hasDefaultValue\":false,\"type\":\"ContractDuration\",\"relationName\":\"ContractToContractDuration\",\"relationFromFields\":[\"contractDurationId\"],\"relationToFields\":[\"id\"],\"isGenerated\":false,\"isUpdatedAt\":false},{\"name\":\"previousContractId\",\"kind\":\"scalar\",\"isList\":false,\"isRequired\":false,\"isUnique\":true,\"isId\":false,\"isReadOnly\":true,\"hasDefaultValue\":false,\"type\":\"Int\",\"isGenerated\":false,\"isUpdatedAt\":false},{\"name\":\"previousContract\",\"kind\":\"object\",\"isList\":false,\"isRequired\":false,\"isUnique\":false,\"isId\":false,\"isReadOnly\":false,\"hasDefaultValue\":false,\"type\":\"Contract\",\"relationName\":\"ContractHistory\",\"relationFromFields\":[\"previousContractId\"],\"relationToFields\":[\"id\"],\"isGenerated\":false,\"isUpdatedAt\":false},{\"name\":\"followUpContract\",\"kind\":\"object\",\"isList\":false,\"isRequired\":false,\"isUnique\":false,\"isId\":false,\"isReadOnly\":false,\"hasDefaultValue\":false,\"type\":\"Contract\",\"relationName\":\"ContractHistory\",\"relationFromFields\":[],\"relationToFields\":[],\"isGenerated\":false,\"isUpdatedAt\":false},{\"name\":\"providerId\",\"kind\":\"scalar\",\"isList\":false,\"isRequired\":false,\"isUnique\":false,\"isId\":false,\"isReadOnly\":true,\"hasDefaultValue\":false,\"type\":\"Int\",\"isGenerated\":false,\"isUpdatedAt\":false},{\"name\":\"provider\",\"kind\":\"object\",\"isList\":false,\"isRequired\":false,\"isUnique\":false,\"isId\":false,\"isReadOnly\":false,\"hasDefaultValue\":false,\"type\":\"Provider\",\"relationName\":\"ContractToProvider\",\"relationFromFields\":[\"providerId\"],\"relationToFields\":[\"id\"],\"isGenerated\":false,\"isUpdatedAt\":false},{\"name\":\"tariffId\",\"kind\":\"scalar\",\"isList\":false,\"isRequired\":false,\"isUnique\":false,\"isId\":false,\"isReadOnly\":true,\"hasDefaultValue\":false,\"type\":\"Int\",\"isGenerated\":false,\"isUpdatedAt\":false},{\"name\":\"tariff\",\"kind\":\"object\",\"isList\":false,\"isRequired\":false,\"isUnique\":false,\"isId\":false,\"isReadOnly\":false,\"hasDefaultValue\":false,\"type\":\"Tariff\",\"relationName\":\"ContractToTariff\",\"relationFromFields\":[\"tariffId\"],\"relationToFields\":[\"id\"],\"isGenerated\":false,\"isUpdatedAt\":false},{\"name\":\"providerName\",\"kind\":\"scalar\",\"isList\":false,\"isRequired\":false,\"isUnique\":false,\"isId\":false,\"isReadOnly\":false,\"hasDefaultValue\":false,\"type\":\"String\",\"isGenerated\":false,\"isUpdatedAt\":false},{\"name\":\"tariffName\",\"kind\":\"scalar\",\"isList\":false,\"isRequired\":false,\"isUnique\":false,\"isId\":false,\"isReadOnly\":false,\"hasDefaultValue\":false,\"type\":\"String\",\"isGenerated\":false,\"isUpdatedAt\":false},{\"name\":\"customerNumberAtProvider\",\"kind\":\"scalar\",\"isList\":false,\"isRequired\":false,\"isUnique\":false,\"isId\":false,\"isReadOnly\":false,\"hasDefaultValue\":false,\"type\":\"String\",\"isGenerated\":false,\"isUpdatedAt\":false},{\"name\":\"priceFirst12Months\",\"kind\":\"scalar\",\"isList\":false,\"isRequired\":false,\"isUnique\":false,\"isId\":false,\"isReadOnly\":false,\"hasDefaultValue\":false,\"type\":\"String\",\"isGenerated\":false,\"isUpdatedAt\":false},{\"name\":\"priceFrom13Months\",\"kind\":\"scalar\",\"isList\":false,\"isRequired\":false,\"isUnique\":false,\"isId\":false,\"isReadOnly\":false,\"hasDefaultValue\":false,\"type\":\"String\",\"isGenerated\":false,\"isUpdatedAt\":false},{\"name\":\"priceAfter24Months\",\"kind\":\"scalar\",\"isList\":false,\"isRequired\":false,\"isUnique\":false,\"isId\":false,\"isReadOnly\":false,\"hasDefaultValue\":false,\"type\":\"String\",\"isGenerated\":false,\"isUpdatedAt\":false},{\"name\":\"startDate\",\"kind\":\"scalar\",\"isList\":false,\"isRequired\":false,\"isUnique\":false,\"isId\":false,\"isReadOnly\":false,\"hasDefaultValue\":false,\"type\":\"DateTime\",\"isGenerated\":false,\"isUpdatedAt\":false},{\"name\":\"endDate\",\"kind\":\"scalar\",\"isList\":false,\"isRequired\":false,\"isUnique\":false,\"isId\":false,\"isReadOnly\":false,\"hasDefaultValue\":false,\"type\":\"DateTime\",\"isGenerated\":false,\"isUpdatedAt\":false},{\"name\":\"commission\",\"kind\":\"scalar\",\"isList\":false,\"isRequired\":false,\"isUnique\":false,\"isId\":false,\"isReadOnly\":false,\"hasDefaultValue\":false,\"type\":\"Float\",\"isGenerated\":false,\"isUpdatedAt\":false},{\"name\":\"cancellationLetterPath\",\"kind\":\"scalar\",\"isList\":false,\"isRequired\":false,\"isUnique\":false,\"isId\":false,\"isReadOnly\":false,\"hasDefaultValue\":false,\"type\":\"String\",\"isGenerated\":false,\"isUpdatedAt\":false},{\"name\":\"cancellationConfirmationPath\",\"kind\":\"scalar\",\"isList\":false,\"isRequired\":false,\"isUnique\":false,\"isId\":false,\"isReadOnly\":false,\"hasDefaultValue\":false,\"type\":\"String\",\"isGenerated\":false,\"isUpdatedAt\":false},{\"name\":\"cancellationLetterOptionsPath\",\"kind\":\"scalar\",\"isList\":false,\"isRequired\":false,\"isUnique\":false,\"isId\":false,\"isReadOnly\":false,\"hasDefaultValue\":false,\"type\":\"String\",\"isGenerated\":false,\"isUpdatedAt\":false},{\"name\":\"cancellationConfirmationOptionsPath\",\"kind\":\"scalar\",\"isList\":false,\"isRequired\":false,\"isUnique\":false,\"isId\":false,\"isReadOnly\":false,\"hasDefaultValue\":false,\"type\":\"String\",\"isGenerated\":false,\"isUpdatedAt\":false},{\"name\":\"cancellationConfirmationDate\",\"kind\":\"scalar\",\"isList\":false,\"isRequired\":false,\"isUnique\":false,\"isId\":false,\"isReadOnly\":false,\"hasDefaultValue\":false,\"type\":\"DateTime\",\"isGenerated\":false,\"isUpdatedAt\":false},{\"name\":\"cancellationConfirmationOptionsDate\",\"kind\":\"scalar\",\"isList\":false,\"isRequired\":false,\"isUnique\":false,\"isId\":false,\"isReadOnly\":false,\"hasDefaultValue\":false,\"type\":\"DateTime\",\"isGenerated\":false,\"isUpdatedAt\":false},{\"name\":\"wasSpecialCancellation\",\"kind\":\"scalar\",\"isList\":false,\"isRequired\":true,\"isUnique\":false,\"isId\":false,\"isReadOnly\":false,\"hasDefaultValue\":true,\"type\":\"Boolean\",\"default\":false,\"isGenerated\":false,\"isUpdatedAt\":false},{\"name\":\"portalUsername\",\"kind\":\"scalar\",\"isList\":false,\"isRequired\":false,\"isUnique\":false,\"isId\":false,\"isReadOnly\":false,\"hasDefaultValue\":false,\"type\":\"String\",\"isGenerated\":false,\"isUpdatedAt\":false},{\"name\":\"portalPasswordEncrypted\",\"kind\":\"scalar\",\"isList\":false,\"isRequired\":false,\"isUnique\":false,\"isId\":false,\"isReadOnly\":false,\"hasDefaultValue\":false,\"type\":\"String\",\"isGenerated\":false,\"isUpdatedAt\":false},{\"name\":\"stressfreiEmailId\",\"kind\":\"scalar\",\"isList\":false,\"isRequired\":false,\"isUnique\":false,\"isId\":false,\"isReadOnly\":true,\"hasDefaultValue\":false,\"type\":\"Int\",\"isGenerated\":false,\"isUpdatedAt\":false},{\"name\":\"stressfreiEmail\",\"kind\":\"object\",\"isList\":false,\"isRequired\":false,\"isUnique\":false,\"isId\":false,\"isReadOnly\":false,\"hasDefaultValue\":false,\"type\":\"StressfreiEmail\",\"relationName\":\"ContractToStressfreiEmail\",\"relationFromFields\":[\"stressfreiEmailId\"],\"relationToFields\":[\"id\"],\"isGenerated\":false,\"isUpdatedAt\":false},{\"name\":\"notes\",\"kind\":\"scalar\",\"isList\":false,\"isRequired\":false,\"isUnique\":false,\"isId\":false,\"isReadOnly\":false,\"hasDefaultValue\":false,\"type\":\"String\",\"isGenerated\":false,\"isUpdatedAt\":false},{\"name\":\"energyDetails\",\"kind\":\"object\",\"isList\":false,\"isRequired\":false,\"isUnique\":false,\"isId\":false,\"isReadOnly\":false,\"hasDefaultValue\":false,\"type\":\"EnergyContractDetails\",\"relationName\":\"ContractToEnergyContractDetails\",\"relationFromFields\":[],\"relationToFields\":[],\"isGenerated\":false,\"isUpdatedAt\":false},{\"name\":\"internetDetails\",\"kind\":\"object\",\"isList\":false,\"isRequired\":false,\"isUnique\":false,\"isId\":false,\"isReadOnly\":false,\"hasDefaultValue\":false,\"type\":\"InternetContractDetails\",\"relationName\":\"ContractToInternetContractDetails\",\"relationFromFields\":[],\"relationToFields\":[],\"isGenerated\":false,\"isUpdatedAt\":false},{\"name\":\"mobileDetails\",\"kind\":\"object\",\"isList\":false,\"isRequired\":false,\"isUnique\":false,\"isId\":false,\"isReadOnly\":false,\"hasDefaultValue\":false,\"type\":\"MobileContractDetails\",\"relationName\":\"ContractToMobileContractDetails\",\"relationFromFields\":[],\"relationToFields\":[],\"isGenerated\":false,\"isUpdatedAt\":false},{\"name\":\"tvDetails\",\"kind\":\"object\",\"isList\":false,\"isRequired\":false,\"isUnique\":false,\"isId\":false,\"isReadOnly\":false,\"hasDefaultValue\":false,\"type\":\"TvContractDetails\",\"relationName\":\"ContractToTvContractDetails\",\"relationFromFields\":[],\"relationToFields\":[],\"isGenerated\":false,\"isUpdatedAt\":false},{\"name\":\"carInsuranceDetails\",\"kind\":\"object\",\"isList\":false,\"isRequired\":false,\"isUnique\":false,\"isId\":false,\"isReadOnly\":false,\"hasDefaultValue\":false,\"type\":\"CarInsuranceDetails\",\"relationName\":\"CarInsuranceDetailsToContract\",\"relationFromFields\":[],\"relationToFields\":[],\"isGenerated\":false,\"isUpdatedAt\":false},{\"name\":\"tasks\",\"kind\":\"object\",\"isList\":true,\"isRequired\":true,\"isUnique\":false,\"isId\":false,\"isReadOnly\":false,\"hasDefaultValue\":false,\"type\":\"ContractTask\",\"relationName\":\"ContractToContractTask\",\"relationFromFields\":[],\"relationToFields\":[],\"isGenerated\":false,\"isUpdatedAt\":false},{\"name\":\"assignedEmails\",\"kind\":\"object\",\"isList\":true,\"isRequired\":true,\"isUnique\":false,\"isId\":false,\"isReadOnly\":false,\"hasDefaultValue\":false,\"type\":\"CachedEmail\",\"relationName\":\"CachedEmailToContract\",\"relationFromFields\":[],\"relationToFields\":[],\"isGenerated\":false,\"isUpdatedAt\":false},{\"name\":\"createdAt\",\"kind\":\"scalar\",\"isList\":false,\"isRequired\":true,\"isUnique\":false,\"isId\":false,\"isReadOnly\":false,\"hasDefaultValue\":true,\"type\":\"DateTime\",\"default\":{\"name\":\"now\",\"args\":[]},\"isGenerated\":false,\"isUpdatedAt\":false},{\"name\":\"updatedAt\",\"kind\":\"scalar\",\"isList\":false,\"isRequired\":true,\"isUnique\":false,\"isId\":false,\"isReadOnly\":false,\"hasDefaultValue\":false,\"type\":\"DateTime\",\"isGenerated\":false,\"isUpdatedAt\":true}],\"primaryKey\":null,\"uniqueFields\":[],\"uniqueIndexes\":[],\"isGenerated\":false},\"ContractTask\":{\"dbName\":null,\"fields\":[{\"name\":\"id\",\"kind\":\"scalar\",\"isList\":false,\"isRequired\":true,\"isUnique\":false,\"isId\":true,\"isReadOnly\":false,\"hasDefaultValue\":true,\"type\":\"Int\",\"default\":{\"name\":\"autoincrement\",\"args\":[]},\"isGenerated\":false,\"isUpdatedAt\":false},{\"name\":\"contractId\",\"kind\":\"scalar\",\"isList\":false,\"isRequired\":true,\"isUnique\":false,\"isId\":false,\"isReadOnly\":true,\"hasDefaultValue\":false,\"type\":\"Int\",\"isGenerated\":false,\"isUpdatedAt\":false},{\"name\":\"contract\",\"kind\":\"object\",\"isList\":false,\"isRequired\":true,\"isUnique\":false,\"isId\":false,\"isReadOnly\":false,\"hasDefaultValue\":false,\"type\":\"Contract\",\"relationName\":\"ContractToContractTask\",\"relationFromFields\":[\"contractId\"],\"relationToFields\":[\"id\"],\"relationOnDelete\":\"Cascade\",\"isGenerated\":false,\"isUpdatedAt\":false},{\"name\":\"title\",\"kind\":\"scalar\",\"isList\":false,\"isRequired\":true,\"isUnique\":false,\"isId\":false,\"isReadOnly\":false,\"hasDefaultValue\":false,\"type\":\"String\",\"isGenerated\":false,\"isUpdatedAt\":false},{\"name\":\"description\",\"kind\":\"scalar\",\"isList\":false,\"isRequired\":false,\"isUnique\":false,\"isId\":false,\"isReadOnly\":false,\"hasDefaultValue\":false,\"type\":\"String\",\"isGenerated\":false,\"isUpdatedAt\":false},{\"name\":\"status\",\"kind\":\"enum\",\"isList\":false,\"isRequired\":true,\"isUnique\":false,\"isId\":false,\"isReadOnly\":false,\"hasDefaultValue\":true,\"type\":\"ContractTaskStatus\",\"default\":\"OPEN\",\"isGenerated\":false,\"isUpdatedAt\":false},{\"name\":\"visibleInPortal\",\"kind\":\"scalar\",\"isList\":false,\"isRequired\":true,\"isUnique\":false,\"isId\":false,\"isReadOnly\":false,\"hasDefaultValue\":true,\"type\":\"Boolean\",\"default\":false,\"isGenerated\":false,\"isUpdatedAt\":false},{\"name\":\"createdBy\",\"kind\":\"scalar\",\"isList\":false,\"isRequired\":false,\"isUnique\":false,\"isId\":false,\"isReadOnly\":false,\"hasDefaultValue\":false,\"type\":\"String\",\"isGenerated\":false,\"isUpdatedAt\":false},{\"name\":\"completedAt\",\"kind\":\"scalar\",\"isList\":false,\"isRequired\":false,\"isUnique\":false,\"isId\":false,\"isReadOnly\":false,\"hasDefaultValue\":false,\"type\":\"DateTime\",\"isGenerated\":false,\"isUpdatedAt\":false},{\"name\":\"subtasks\",\"kind\":\"object\",\"isList\":true,\"isRequired\":true,\"isUnique\":false,\"isId\":false,\"isReadOnly\":false,\"hasDefaultValue\":false,\"type\":\"ContractTaskSubtask\",\"relationName\":\"ContractTaskToContractTaskSubtask\",\"relationFromFields\":[],\"relationToFields\":[],\"isGenerated\":false,\"isUpdatedAt\":false},{\"name\":\"createdAt\",\"kind\":\"scalar\",\"isList\":false,\"isRequired\":true,\"isUnique\":false,\"isId\":false,\"isReadOnly\":false,\"hasDefaultValue\":true,\"type\":\"DateTime\",\"default\":{\"name\":\"now\",\"args\":[]},\"isGenerated\":false,\"isUpdatedAt\":false},{\"name\":\"updatedAt\",\"kind\":\"scalar\",\"isList\":false,\"isRequired\":true,\"isUnique\":false,\"isId\":false,\"isReadOnly\":false,\"hasDefaultValue\":false,\"type\":\"DateTime\",\"isGenerated\":false,\"isUpdatedAt\":true}],\"primaryKey\":null,\"uniqueFields\":[],\"uniqueIndexes\":[],\"isGenerated\":false},\"ContractTaskSubtask\":{\"dbName\":null,\"fields\":[{\"name\":\"id\",\"kind\":\"scalar\",\"isList\":false,\"isRequired\":true,\"isUnique\":false,\"isId\":true,\"isReadOnly\":false,\"hasDefaultValue\":true,\"type\":\"Int\",\"default\":{\"name\":\"autoincrement\",\"args\":[]},\"isGenerated\":false,\"isUpdatedAt\":false},{\"name\":\"taskId\",\"kind\":\"scalar\",\"isList\":false,\"isRequired\":true,\"isUnique\":false,\"isId\":false,\"isReadOnly\":true,\"hasDefaultValue\":false,\"type\":\"Int\",\"isGenerated\":false,\"isUpdatedAt\":false},{\"name\":\"task\",\"kind\":\"object\",\"isList\":false,\"isRequired\":true,\"isUnique\":false,\"isId\":false,\"isReadOnly\":false,\"hasDefaultValue\":false,\"type\":\"ContractTask\",\"relationName\":\"ContractTaskToContractTaskSubtask\",\"relationFromFields\":[\"taskId\"],\"relationToFields\":[\"id\"],\"relationOnDelete\":\"Cascade\",\"isGenerated\":false,\"isUpdatedAt\":false},{\"name\":\"title\",\"kind\":\"scalar\",\"isList\":false,\"isRequired\":true,\"isUnique\":false,\"isId\":false,\"isReadOnly\":false,\"hasDefaultValue\":false,\"type\":\"String\",\"isGenerated\":false,\"isUpdatedAt\":false},{\"name\":\"status\",\"kind\":\"enum\",\"isList\":false,\"isRequired\":true,\"isUnique\":false,\"isId\":false,\"isReadOnly\":false,\"hasDefaultValue\":true,\"type\":\"ContractTaskStatus\",\"default\":\"OPEN\",\"isGenerated\":false,\"isUpdatedAt\":false},{\"name\":\"createdBy\",\"kind\":\"scalar\",\"isList\":false,\"isRequired\":false,\"isUnique\":false,\"isId\":false,\"isReadOnly\":false,\"hasDefaultValue\":false,\"type\":\"String\",\"isGenerated\":false,\"isUpdatedAt\":false},{\"name\":\"completedAt\",\"kind\":\"scalar\",\"isList\":false,\"isRequired\":false,\"isUnique\":false,\"isId\":false,\"isReadOnly\":false,\"hasDefaultValue\":false,\"type\":\"DateTime\",\"isGenerated\":false,\"isUpdatedAt\":false},{\"name\":\"createdAt\",\"kind\":\"scalar\",\"isList\":false,\"isRequired\":true,\"isUnique\":false,\"isId\":false,\"isReadOnly\":false,\"hasDefaultValue\":true,\"type\":\"DateTime\",\"default\":{\"name\":\"now\",\"args\":[]},\"isGenerated\":false,\"isUpdatedAt\":false},{\"name\":\"updatedAt\",\"kind\":\"scalar\",\"isList\":false,\"isRequired\":true,\"isUnique\":false,\"isId\":false,\"isReadOnly\":false,\"hasDefaultValue\":false,\"type\":\"DateTime\",\"isGenerated\":false,\"isUpdatedAt\":true}],\"primaryKey\":null,\"uniqueFields\":[],\"uniqueIndexes\":[],\"isGenerated\":false},\"EnergyContractDetails\":{\"dbName\":null,\"fields\":[{\"name\":\"id\",\"kind\":\"scalar\",\"isList\":false,\"isRequired\":true,\"isUnique\":false,\"isId\":true,\"isReadOnly\":false,\"hasDefaultValue\":true,\"type\":\"Int\",\"default\":{\"name\":\"autoincrement\",\"args\":[]},\"isGenerated\":false,\"isUpdatedAt\":false},{\"name\":\"contractId\",\"kind\":\"scalar\",\"isList\":false,\"isRequired\":true,\"isUnique\":true,\"isId\":false,\"isReadOnly\":true,\"hasDefaultValue\":false,\"type\":\"Int\",\"isGenerated\":false,\"isUpdatedAt\":false},{\"name\":\"contract\",\"kind\":\"object\",\"isList\":false,\"isRequired\":true,\"isUnique\":false,\"isId\":false,\"isReadOnly\":false,\"hasDefaultValue\":false,\"type\":\"Contract\",\"relationName\":\"ContractToEnergyContractDetails\",\"relationFromFields\":[\"contractId\"],\"relationToFields\":[\"id\"],\"relationOnDelete\":\"Cascade\",\"isGenerated\":false,\"isUpdatedAt\":false},{\"name\":\"meterId\",\"kind\":\"scalar\",\"isList\":false,\"isRequired\":false,\"isUnique\":false,\"isId\":false,\"isReadOnly\":true,\"hasDefaultValue\":false,\"type\":\"Int\",\"isGenerated\":false,\"isUpdatedAt\":false},{\"name\":\"meter\",\"kind\":\"object\",\"isList\":false,\"isRequired\":false,\"isUnique\":false,\"isId\":false,\"isReadOnly\":false,\"hasDefaultValue\":false,\"type\":\"Meter\",\"relationName\":\"EnergyContractDetailsToMeter\",\"relationFromFields\":[\"meterId\"],\"relationToFields\":[\"id\"],\"isGenerated\":false,\"isUpdatedAt\":false},{\"name\":\"annualConsumption\",\"kind\":\"scalar\",\"isList\":false,\"isRequired\":false,\"isUnique\":false,\"isId\":false,\"isReadOnly\":false,\"hasDefaultValue\":false,\"type\":\"Float\",\"isGenerated\":false,\"isUpdatedAt\":false},{\"name\":\"basePrice\",\"kind\":\"scalar\",\"isList\":false,\"isRequired\":false,\"isUnique\":false,\"isId\":false,\"isReadOnly\":false,\"hasDefaultValue\":false,\"type\":\"Float\",\"isGenerated\":false,\"isUpdatedAt\":false},{\"name\":\"unitPrice\",\"kind\":\"scalar\",\"isList\":false,\"isRequired\":false,\"isUnique\":false,\"isId\":false,\"isReadOnly\":false,\"hasDefaultValue\":false,\"type\":\"Float\",\"isGenerated\":false,\"isUpdatedAt\":false},{\"name\":\"bonus\",\"kind\":\"scalar\",\"isList\":false,\"isRequired\":false,\"isUnique\":false,\"isId\":false,\"isReadOnly\":false,\"hasDefaultValue\":false,\"type\":\"Float\",\"isGenerated\":false,\"isUpdatedAt\":false},{\"name\":\"previousProviderName\",\"kind\":\"scalar\",\"isList\":false,\"isRequired\":false,\"isUnique\":false,\"isId\":false,\"isReadOnly\":false,\"hasDefaultValue\":false,\"type\":\"String\",\"isGenerated\":false,\"isUpdatedAt\":false},{\"name\":\"previousCustomerNumber\",\"kind\":\"scalar\",\"isList\":false,\"isRequired\":false,\"isUnique\":false,\"isId\":false,\"isReadOnly\":false,\"hasDefaultValue\":false,\"type\":\"String\",\"isGenerated\":false,\"isUpdatedAt\":false}],\"primaryKey\":null,\"uniqueFields\":[],\"uniqueIndexes\":[],\"isGenerated\":false},\"InternetContractDetails\":{\"dbName\":null,\"fields\":[{\"name\":\"id\",\"kind\":\"scalar\",\"isList\":false,\"isRequired\":true,\"isUnique\":false,\"isId\":true,\"isReadOnly\":false,\"hasDefaultValue\":true,\"type\":\"Int\",\"default\":{\"name\":\"autoincrement\",\"args\":[]},\"isGenerated\":false,\"isUpdatedAt\":false},{\"name\":\"contractId\",\"kind\":\"scalar\",\"isList\":false,\"isRequired\":true,\"isUnique\":true,\"isId\":false,\"isReadOnly\":true,\"hasDefaultValue\":false,\"type\":\"Int\",\"isGenerated\":false,\"isUpdatedAt\":false},{\"name\":\"contract\",\"kind\":\"object\",\"isList\":false,\"isRequired\":true,\"isUnique\":false,\"isId\":false,\"isReadOnly\":false,\"hasDefaultValue\":false,\"type\":\"Contract\",\"relationName\":\"ContractToInternetContractDetails\",\"relationFromFields\":[\"contractId\"],\"relationToFields\":[\"id\"],\"relationOnDelete\":\"Cascade\",\"isGenerated\":false,\"isUpdatedAt\":false},{\"name\":\"downloadSpeed\",\"kind\":\"scalar\",\"isList\":false,\"isRequired\":false,\"isUnique\":false,\"isId\":false,\"isReadOnly\":false,\"hasDefaultValue\":false,\"type\":\"Int\",\"isGenerated\":false,\"isUpdatedAt\":false},{\"name\":\"uploadSpeed\",\"kind\":\"scalar\",\"isList\":false,\"isRequired\":false,\"isUnique\":false,\"isId\":false,\"isReadOnly\":false,\"hasDefaultValue\":false,\"type\":\"Int\",\"isGenerated\":false,\"isUpdatedAt\":false},{\"name\":\"routerModel\",\"kind\":\"scalar\",\"isList\":false,\"isRequired\":false,\"isUnique\":false,\"isId\":false,\"isReadOnly\":false,\"hasDefaultValue\":false,\"type\":\"String\",\"isGenerated\":false,\"isUpdatedAt\":false},{\"name\":\"routerSerialNumber\",\"kind\":\"scalar\",\"isList\":false,\"isRequired\":false,\"isUnique\":false,\"isId\":false,\"isReadOnly\":false,\"hasDefaultValue\":false,\"type\":\"String\",\"isGenerated\":false,\"isUpdatedAt\":false},{\"name\":\"installationDate\",\"kind\":\"scalar\",\"isList\":false,\"isRequired\":false,\"isUnique\":false,\"isId\":false,\"isReadOnly\":false,\"hasDefaultValue\":false,\"type\":\"DateTime\",\"isGenerated\":false,\"isUpdatedAt\":false},{\"name\":\"internetUsername\",\"kind\":\"scalar\",\"isList\":false,\"isRequired\":false,\"isUnique\":false,\"isId\":false,\"isReadOnly\":false,\"hasDefaultValue\":false,\"type\":\"String\",\"isGenerated\":false,\"isUpdatedAt\":false},{\"name\":\"internetPasswordEncrypted\",\"kind\":\"scalar\",\"isList\":false,\"isRequired\":false,\"isUnique\":false,\"isId\":false,\"isReadOnly\":false,\"hasDefaultValue\":false,\"type\":\"String\",\"isGenerated\":false,\"isUpdatedAt\":false},{\"name\":\"homeId\",\"kind\":\"scalar\",\"isList\":false,\"isRequired\":false,\"isUnique\":false,\"isId\":false,\"isReadOnly\":false,\"hasDefaultValue\":false,\"type\":\"String\",\"isGenerated\":false,\"isUpdatedAt\":false},{\"name\":\"activationCode\",\"kind\":\"scalar\",\"isList\":false,\"isRequired\":false,\"isUnique\":false,\"isId\":false,\"isReadOnly\":false,\"hasDefaultValue\":false,\"type\":\"String\",\"isGenerated\":false,\"isUpdatedAt\":false},{\"name\":\"phoneNumbers\",\"kind\":\"object\",\"isList\":true,\"isRequired\":true,\"isUnique\":false,\"isId\":false,\"isReadOnly\":false,\"hasDefaultValue\":false,\"type\":\"PhoneNumber\",\"relationName\":\"InternetContractDetailsToPhoneNumber\",\"relationFromFields\":[],\"relationToFields\":[],\"isGenerated\":false,\"isUpdatedAt\":false}],\"primaryKey\":null,\"uniqueFields\":[],\"uniqueIndexes\":[],\"isGenerated\":false},\"PhoneNumber\":{\"dbName\":null,\"fields\":[{\"name\":\"id\",\"kind\":\"scalar\",\"isList\":false,\"isRequired\":true,\"isUnique\":false,\"isId\":true,\"isReadOnly\":false,\"hasDefaultValue\":true,\"type\":\"Int\",\"default\":{\"name\":\"autoincrement\",\"args\":[]},\"isGenerated\":false,\"isUpdatedAt\":false},{\"name\":\"internetContractDetailsId\",\"kind\":\"scalar\",\"isList\":false,\"isRequired\":true,\"isUnique\":false,\"isId\":false,\"isReadOnly\":true,\"hasDefaultValue\":false,\"type\":\"Int\",\"isGenerated\":false,\"isUpdatedAt\":false},{\"name\":\"internetDetails\",\"kind\":\"object\",\"isList\":false,\"isRequired\":true,\"isUnique\":false,\"isId\":false,\"isReadOnly\":false,\"hasDefaultValue\":false,\"type\":\"InternetContractDetails\",\"relationName\":\"InternetContractDetailsToPhoneNumber\",\"relationFromFields\":[\"internetContractDetailsId\"],\"relationToFields\":[\"id\"],\"relationOnDelete\":\"Cascade\",\"isGenerated\":false,\"isUpdatedAt\":false},{\"name\":\"phoneNumber\",\"kind\":\"scalar\",\"isList\":false,\"isRequired\":true,\"isUnique\":false,\"isId\":false,\"isReadOnly\":false,\"hasDefaultValue\":false,\"type\":\"String\",\"isGenerated\":false,\"isUpdatedAt\":false},{\"name\":\"isMain\",\"kind\":\"scalar\",\"isList\":false,\"isRequired\":true,\"isUnique\":false,\"isId\":false,\"isReadOnly\":false,\"hasDefaultValue\":true,\"type\":\"Boolean\",\"default\":false,\"isGenerated\":false,\"isUpdatedAt\":false},{\"name\":\"sipUsername\",\"kind\":\"scalar\",\"isList\":false,\"isRequired\":false,\"isUnique\":false,\"isId\":false,\"isReadOnly\":false,\"hasDefaultValue\":false,\"type\":\"String\",\"isGenerated\":false,\"isUpdatedAt\":false},{\"name\":\"sipPasswordEncrypted\",\"kind\":\"scalar\",\"isList\":false,\"isRequired\":false,\"isUnique\":false,\"isId\":false,\"isReadOnly\":false,\"hasDefaultValue\":false,\"type\":\"String\",\"isGenerated\":false,\"isUpdatedAt\":false},{\"name\":\"sipServer\",\"kind\":\"scalar\",\"isList\":false,\"isRequired\":false,\"isUnique\":false,\"isId\":false,\"isReadOnly\":false,\"hasDefaultValue\":false,\"type\":\"String\",\"isGenerated\":false,\"isUpdatedAt\":false}],\"primaryKey\":null,\"uniqueFields\":[],\"uniqueIndexes\":[],\"isGenerated\":false},\"MobileContractDetails\":{\"dbName\":null,\"fields\":[{\"name\":\"id\",\"kind\":\"scalar\",\"isList\":false,\"isRequired\":true,\"isUnique\":false,\"isId\":true,\"isReadOnly\":false,\"hasDefaultValue\":true,\"type\":\"Int\",\"default\":{\"name\":\"autoincrement\",\"args\":[]},\"isGenerated\":false,\"isUpdatedAt\":false},{\"name\":\"contractId\",\"kind\":\"scalar\",\"isList\":false,\"isRequired\":true,\"isUnique\":true,\"isId\":false,\"isReadOnly\":true,\"hasDefaultValue\":false,\"type\":\"Int\",\"isGenerated\":false,\"isUpdatedAt\":false},{\"name\":\"contract\",\"kind\":\"object\",\"isList\":false,\"isRequired\":true,\"isUnique\":false,\"isId\":false,\"isReadOnly\":false,\"hasDefaultValue\":false,\"type\":\"Contract\",\"relationName\":\"ContractToMobileContractDetails\",\"relationFromFields\":[\"contractId\"],\"relationToFields\":[\"id\"],\"relationOnDelete\":\"Cascade\",\"isGenerated\":false,\"isUpdatedAt\":false},{\"name\":\"requiresMultisim\",\"kind\":\"scalar\",\"isList\":false,\"isRequired\":true,\"isUnique\":false,\"isId\":false,\"isReadOnly\":false,\"hasDefaultValue\":true,\"type\":\"Boolean\",\"default\":false,\"isGenerated\":false,\"isUpdatedAt\":false},{\"name\":\"dataVolume\",\"kind\":\"scalar\",\"isList\":false,\"isRequired\":false,\"isUnique\":false,\"isId\":false,\"isReadOnly\":false,\"hasDefaultValue\":false,\"type\":\"Float\",\"isGenerated\":false,\"isUpdatedAt\":false},{\"name\":\"includedMinutes\",\"kind\":\"scalar\",\"isList\":false,\"isRequired\":false,\"isUnique\":false,\"isId\":false,\"isReadOnly\":false,\"hasDefaultValue\":false,\"type\":\"Int\",\"isGenerated\":false,\"isUpdatedAt\":false},{\"name\":\"includedSMS\",\"kind\":\"scalar\",\"isList\":false,\"isRequired\":false,\"isUnique\":false,\"isId\":false,\"isReadOnly\":false,\"hasDefaultValue\":false,\"type\":\"Int\",\"isGenerated\":false,\"isUpdatedAt\":false},{\"name\":\"deviceModel\",\"kind\":\"scalar\",\"isList\":false,\"isRequired\":false,\"isUnique\":false,\"isId\":false,\"isReadOnly\":false,\"hasDefaultValue\":false,\"type\":\"String\",\"isGenerated\":false,\"isUpdatedAt\":false},{\"name\":\"deviceImei\",\"kind\":\"scalar\",\"isList\":false,\"isRequired\":false,\"isUnique\":false,\"isId\":false,\"isReadOnly\":false,\"hasDefaultValue\":false,\"type\":\"String\",\"isGenerated\":false,\"isUpdatedAt\":false},{\"name\":\"simCards\",\"kind\":\"object\",\"isList\":true,\"isRequired\":true,\"isUnique\":false,\"isId\":false,\"isReadOnly\":false,\"hasDefaultValue\":false,\"type\":\"SimCard\",\"relationName\":\"MobileContractDetailsToSimCard\",\"relationFromFields\":[],\"relationToFields\":[],\"isGenerated\":false,\"isUpdatedAt\":false},{\"name\":\"phoneNumber\",\"kind\":\"scalar\",\"isList\":false,\"isRequired\":false,\"isUnique\":false,\"isId\":false,\"isReadOnly\":false,\"hasDefaultValue\":false,\"type\":\"String\",\"isGenerated\":false,\"isUpdatedAt\":false},{\"name\":\"simCardNumber\",\"kind\":\"scalar\",\"isList\":false,\"isRequired\":false,\"isUnique\":false,\"isId\":false,\"isReadOnly\":false,\"hasDefaultValue\":false,\"type\":\"String\",\"isGenerated\":false,\"isUpdatedAt\":false}],\"primaryKey\":null,\"uniqueFields\":[],\"uniqueIndexes\":[],\"isGenerated\":false},\"SimCard\":{\"dbName\":null,\"fields\":[{\"name\":\"id\",\"kind\":\"scalar\",\"isList\":false,\"isRequired\":true,\"isUnique\":false,\"isId\":true,\"isReadOnly\":false,\"hasDefaultValue\":true,\"type\":\"Int\",\"default\":{\"name\":\"autoincrement\",\"args\":[]},\"isGenerated\":false,\"isUpdatedAt\":false},{\"name\":\"mobileDetailsId\",\"kind\":\"scalar\",\"isList\":false,\"isRequired\":true,\"isUnique\":false,\"isId\":false,\"isReadOnly\":true,\"hasDefaultValue\":false,\"type\":\"Int\",\"isGenerated\":false,\"isUpdatedAt\":false},{\"name\":\"mobileDetails\",\"kind\":\"object\",\"isList\":false,\"isRequired\":true,\"isUnique\":false,\"isId\":false,\"isReadOnly\":false,\"hasDefaultValue\":false,\"type\":\"MobileContractDetails\",\"relationName\":\"MobileContractDetailsToSimCard\",\"relationFromFields\":[\"mobileDetailsId\"],\"relationToFields\":[\"id\"],\"relationOnDelete\":\"Cascade\",\"isGenerated\":false,\"isUpdatedAt\":false},{\"name\":\"phoneNumber\",\"kind\":\"scalar\",\"isList\":false,\"isRequired\":false,\"isUnique\":false,\"isId\":false,\"isReadOnly\":false,\"hasDefaultValue\":false,\"type\":\"String\",\"isGenerated\":false,\"isUpdatedAt\":false},{\"name\":\"simCardNumber\",\"kind\":\"scalar\",\"isList\":false,\"isRequired\":false,\"isUnique\":false,\"isId\":false,\"isReadOnly\":false,\"hasDefaultValue\":false,\"type\":\"String\",\"isGenerated\":false,\"isUpdatedAt\":false},{\"name\":\"pin\",\"kind\":\"scalar\",\"isList\":false,\"isRequired\":false,\"isUnique\":false,\"isId\":false,\"isReadOnly\":false,\"hasDefaultValue\":false,\"type\":\"String\",\"isGenerated\":false,\"isUpdatedAt\":false},{\"name\":\"puk\",\"kind\":\"scalar\",\"isList\":false,\"isRequired\":false,\"isUnique\":false,\"isId\":false,\"isReadOnly\":false,\"hasDefaultValue\":false,\"type\":\"String\",\"isGenerated\":false,\"isUpdatedAt\":false},{\"name\":\"isMultisim\",\"kind\":\"scalar\",\"isList\":false,\"isRequired\":true,\"isUnique\":false,\"isId\":false,\"isReadOnly\":false,\"hasDefaultValue\":true,\"type\":\"Boolean\",\"default\":false,\"isGenerated\":false,\"isUpdatedAt\":false},{\"name\":\"isMain\",\"kind\":\"scalar\",\"isList\":false,\"isRequired\":true,\"isUnique\":false,\"isId\":false,\"isReadOnly\":false,\"hasDefaultValue\":true,\"type\":\"Boolean\",\"default\":false,\"isGenerated\":false,\"isUpdatedAt\":false},{\"name\":\"createdAt\",\"kind\":\"scalar\",\"isList\":false,\"isRequired\":true,\"isUnique\":false,\"isId\":false,\"isReadOnly\":false,\"hasDefaultValue\":true,\"type\":\"DateTime\",\"default\":{\"name\":\"now\",\"args\":[]},\"isGenerated\":false,\"isUpdatedAt\":false},{\"name\":\"updatedAt\",\"kind\":\"scalar\",\"isList\":false,\"isRequired\":true,\"isUnique\":false,\"isId\":false,\"isReadOnly\":false,\"hasDefaultValue\":false,\"type\":\"DateTime\",\"isGenerated\":false,\"isUpdatedAt\":true}],\"primaryKey\":null,\"uniqueFields\":[],\"uniqueIndexes\":[],\"isGenerated\":false},\"TvContractDetails\":{\"dbName\":null,\"fields\":[{\"name\":\"id\",\"kind\":\"scalar\",\"isList\":false,\"isRequired\":true,\"isUnique\":false,\"isId\":true,\"isReadOnly\":false,\"hasDefaultValue\":true,\"type\":\"Int\",\"default\":{\"name\":\"autoincrement\",\"args\":[]},\"isGenerated\":false,\"isUpdatedAt\":false},{\"name\":\"contractId\",\"kind\":\"scalar\",\"isList\":false,\"isRequired\":true,\"isUnique\":true,\"isId\":false,\"isReadOnly\":true,\"hasDefaultValue\":false,\"type\":\"Int\",\"isGenerated\":false,\"isUpdatedAt\":false},{\"name\":\"contract\",\"kind\":\"object\",\"isList\":false,\"isRequired\":true,\"isUnique\":false,\"isId\":false,\"isReadOnly\":false,\"hasDefaultValue\":false,\"type\":\"Contract\",\"relationName\":\"ContractToTvContractDetails\",\"relationFromFields\":[\"contractId\"],\"relationToFields\":[\"id\"],\"relationOnDelete\":\"Cascade\",\"isGenerated\":false,\"isUpdatedAt\":false},{\"name\":\"receiverModel\",\"kind\":\"scalar\",\"isList\":false,\"isRequired\":false,\"isUnique\":false,\"isId\":false,\"isReadOnly\":false,\"hasDefaultValue\":false,\"type\":\"String\",\"isGenerated\":false,\"isUpdatedAt\":false},{\"name\":\"smartcardNumber\",\"kind\":\"scalar\",\"isList\":false,\"isRequired\":false,\"isUnique\":false,\"isId\":false,\"isReadOnly\":false,\"hasDefaultValue\":false,\"type\":\"String\",\"isGenerated\":false,\"isUpdatedAt\":false},{\"name\":\"package\",\"kind\":\"scalar\",\"isList\":false,\"isRequired\":false,\"isUnique\":false,\"isId\":false,\"isReadOnly\":false,\"hasDefaultValue\":false,\"type\":\"String\",\"isGenerated\":false,\"isUpdatedAt\":false}],\"primaryKey\":null,\"uniqueFields\":[],\"uniqueIndexes\":[],\"isGenerated\":false},\"CarInsuranceDetails\":{\"dbName\":null,\"fields\":[{\"name\":\"id\",\"kind\":\"scalar\",\"isList\":false,\"isRequired\":true,\"isUnique\":false,\"isId\":true,\"isReadOnly\":false,\"hasDefaultValue\":true,\"type\":\"Int\",\"default\":{\"name\":\"autoincrement\",\"args\":[]},\"isGenerated\":false,\"isUpdatedAt\":false},{\"name\":\"contractId\",\"kind\":\"scalar\",\"isList\":false,\"isRequired\":true,\"isUnique\":true,\"isId\":false,\"isReadOnly\":true,\"hasDefaultValue\":false,\"type\":\"Int\",\"isGenerated\":false,\"isUpdatedAt\":false},{\"name\":\"contract\",\"kind\":\"object\",\"isList\":false,\"isRequired\":true,\"isUnique\":false,\"isId\":false,\"isReadOnly\":false,\"hasDefaultValue\":false,\"type\":\"Contract\",\"relationName\":\"CarInsuranceDetailsToContract\",\"relationFromFields\":[\"contractId\"],\"relationToFields\":[\"id\"],\"relationOnDelete\":\"Cascade\",\"isGenerated\":false,\"isUpdatedAt\":false},{\"name\":\"licensePlate\",\"kind\":\"scalar\",\"isList\":false,\"isRequired\":false,\"isUnique\":false,\"isId\":false,\"isReadOnly\":false,\"hasDefaultValue\":false,\"type\":\"String\",\"isGenerated\":false,\"isUpdatedAt\":false},{\"name\":\"hsn\",\"kind\":\"scalar\",\"isList\":false,\"isRequired\":false,\"isUnique\":false,\"isId\":false,\"isReadOnly\":false,\"hasDefaultValue\":false,\"type\":\"String\",\"isGenerated\":false,\"isUpdatedAt\":false},{\"name\":\"tsn\",\"kind\":\"scalar\",\"isList\":false,\"isRequired\":false,\"isUnique\":false,\"isId\":false,\"isReadOnly\":false,\"hasDefaultValue\":false,\"type\":\"String\",\"isGenerated\":false,\"isUpdatedAt\":false},{\"name\":\"vin\",\"kind\":\"scalar\",\"isList\":false,\"isRequired\":false,\"isUnique\":false,\"isId\":false,\"isReadOnly\":false,\"hasDefaultValue\":false,\"type\":\"String\",\"isGenerated\":false,\"isUpdatedAt\":false},{\"name\":\"vehicleType\",\"kind\":\"scalar\",\"isList\":false,\"isRequired\":false,\"isUnique\":false,\"isId\":false,\"isReadOnly\":false,\"hasDefaultValue\":false,\"type\":\"String\",\"isGenerated\":false,\"isUpdatedAt\":false},{\"name\":\"firstRegistration\",\"kind\":\"scalar\",\"isList\":false,\"isRequired\":false,\"isUnique\":false,\"isId\":false,\"isReadOnly\":false,\"hasDefaultValue\":false,\"type\":\"DateTime\",\"isGenerated\":false,\"isUpdatedAt\":false},{\"name\":\"noClaimsClass\",\"kind\":\"scalar\",\"isList\":false,\"isRequired\":false,\"isUnique\":false,\"isId\":false,\"isReadOnly\":false,\"hasDefaultValue\":false,\"type\":\"String\",\"isGenerated\":false,\"isUpdatedAt\":false},{\"name\":\"insuranceType\",\"kind\":\"enum\",\"isList\":false,\"isRequired\":true,\"isUnique\":false,\"isId\":false,\"isReadOnly\":false,\"hasDefaultValue\":true,\"type\":\"InsuranceType\",\"default\":\"LIABILITY\",\"isGenerated\":false,\"isUpdatedAt\":false},{\"name\":\"deductiblePartial\",\"kind\":\"scalar\",\"isList\":false,\"isRequired\":false,\"isUnique\":false,\"isId\":false,\"isReadOnly\":false,\"hasDefaultValue\":false,\"type\":\"Float\",\"isGenerated\":false,\"isUpdatedAt\":false},{\"name\":\"deductibleFull\",\"kind\":\"scalar\",\"isList\":false,\"isRequired\":false,\"isUnique\":false,\"isId\":false,\"isReadOnly\":false,\"hasDefaultValue\":false,\"type\":\"Float\",\"isGenerated\":false,\"isUpdatedAt\":false},{\"name\":\"policyNumber\",\"kind\":\"scalar\",\"isList\":false,\"isRequired\":false,\"isUnique\":false,\"isId\":false,\"isReadOnly\":false,\"hasDefaultValue\":false,\"type\":\"String\",\"isGenerated\":false,\"isUpdatedAt\":false},{\"name\":\"previousInsurer\",\"kind\":\"scalar\",\"isList\":false,\"isRequired\":false,\"isUnique\":false,\"isId\":false,\"isReadOnly\":false,\"hasDefaultValue\":false,\"type\":\"String\",\"isGenerated\":false,\"isUpdatedAt\":false}],\"primaryKey\":null,\"uniqueFields\":[],\"uniqueIndexes\":[],\"isGenerated\":false}},\"enums\":{\"CustomerType\":{\"values\":[{\"name\":\"PRIVATE\",\"dbName\":null},{\"name\":\"BUSINESS\",\"dbName\":null}],\"dbName\":null},\"AddressType\":{\"values\":[{\"name\":\"DELIVERY_RESIDENCE\",\"dbName\":null},{\"name\":\"BILLING\",\"dbName\":null}],\"dbName\":null},\"DocumentType\":{\"values\":[{\"name\":\"ID_CARD\",\"dbName\":null},{\"name\":\"PASSPORT\",\"dbName\":null},{\"name\":\"DRIVERS_LICENSE\",\"dbName\":null},{\"name\":\"OTHER\",\"dbName\":null}],\"dbName\":null},\"EmailProviderType\":{\"values\":[{\"name\":\"PLESK\",\"dbName\":null},{\"name\":\"CPANEL\",\"dbName\":null},{\"name\":\"DIRECTADMIN\",\"dbName\":null}],\"dbName\":null},\"MailEncryption\":{\"values\":[{\"name\":\"SSL\",\"dbName\":null},{\"name\":\"STARTTLS\",\"dbName\":null},{\"name\":\"NONE\",\"dbName\":null}],\"dbName\":null},\"EmailFolder\":{\"values\":[{\"name\":\"INBOX\",\"dbName\":null},{\"name\":\"SENT\",\"dbName\":null}],\"dbName\":null},\"MeterType\":{\"values\":[{\"name\":\"ELECTRICITY\",\"dbName\":null},{\"name\":\"GAS\",\"dbName\":null}],\"dbName\":null},\"ContractType\":{\"values\":[{\"name\":\"ELECTRICITY\",\"dbName\":null},{\"name\":\"GAS\",\"dbName\":null},{\"name\":\"DSL\",\"dbName\":null},{\"name\":\"CABLE\",\"dbName\":null},{\"name\":\"FIBER\",\"dbName\":null},{\"name\":\"MOBILE\",\"dbName\":null},{\"name\":\"TV\",\"dbName\":null},{\"name\":\"CAR_INSURANCE\",\"dbName\":null}],\"dbName\":null},\"ContractStatus\":{\"values\":[{\"name\":\"DRAFT\",\"dbName\":null},{\"name\":\"PENDING\",\"dbName\":null},{\"name\":\"ACTIVE\",\"dbName\":null},{\"name\":\"CANCELLED\",\"dbName\":null},{\"name\":\"EXPIRED\",\"dbName\":null},{\"name\":\"DEACTIVATED\",\"dbName\":null}],\"dbName\":null},\"ContractTaskStatus\":{\"values\":[{\"name\":\"OPEN\",\"dbName\":null},{\"name\":\"COMPLETED\",\"dbName\":null}],\"dbName\":null},\"InsuranceType\":{\"values\":[{\"name\":\"LIABILITY\",\"dbName\":null},{\"name\":\"PARTIAL\",\"dbName\":null},{\"name\":\"FULL\",\"dbName\":null}],\"dbName\":null}},\"types\":{}}") defineDmmfProperty(exports.Prisma, config.runtimeDataModel) config.engineWasm = undefined diff --git a/backend/node_modules/.prisma/client/package.json b/backend/node_modules/.prisma/client/package.json index c06e07ed..7c4248b1 100644 --- a/backend/node_modules/.prisma/client/package.json +++ b/backend/node_modules/.prisma/client/package.json @@ -1,5 +1,5 @@ { - "name": "prisma-client-f3be941c86c0d933a2a09d69aafc49ad121411869df4ce4f365fdf53679b90db", + "name": "prisma-client-3c4bb688688ba372393d0bf86523c07e8b4de3ff0d9ad23a89f905f15047a1a5", "main": "index.js", "types": "index.d.ts", "browser": "index-browser.js", diff --git a/backend/node_modules/.prisma/client/schema.prisma b/backend/node_modules/.prisma/client/schema.prisma index b705919f..2138f684 100644 --- a/backend/node_modules/.prisma/client/schema.prisma +++ b/backend/node_modules/.prisma/client/schema.prisma @@ -20,17 +20,18 @@ model AppSetting { // ==================== USERS & AUTH ==================== model User { - id Int @id @default(autoincrement()) - email String @unique - password String - firstName String - lastName String - isActive Boolean @default(true) - customerId Int? @unique - customer Customer? @relation(fields: [customerId], references: [id]) - roles UserRole[] - createdAt DateTime @default(now()) - updatedAt DateTime @updatedAt + id Int @id @default(autoincrement()) + email String @unique + password String + firstName String + lastName String + isActive Boolean @default(true) + tokenInvalidatedAt DateTime? // Zeitpunkt ab dem alle Tokens ungültig sind (für Zwangslogout bei Rechteänderung) + customerId Int? @unique + customer Customer? @relation(fields: [customerId], references: [id]) + roles UserRole[] + createdAt DateTime @default(now()) + updatedAt DateTime @updatedAt } model Role { @@ -216,6 +217,13 @@ enum EmailProviderType { DIRECTADMIN } +// Verschlüsselungstyp für E-Mail-Verbindungen +enum MailEncryption { + SSL // Implicit SSL/TLS (Ports 465/993) - Verschlüsselung von Anfang an + STARTTLS // STARTTLS (Ports 587/143) - Startet unverschlüsselt, dann Upgrade + NONE // Keine Verschlüsselung (Ports 25/143) +} + model EmailProviderConfig { id Int @id @default(autoincrement()) name String @unique // z.B. "Plesk Hauptserver" @@ -226,28 +234,103 @@ model EmailProviderConfig { passwordEncrypted String? // Passwort (verschlüsselt) domain String // Domain für E-Mails (z.B. stressfrei-wechseln.de) defaultForwardEmail String? // Standard-Weiterleitungsadresse (unsere eigene) - isActive Boolean @default(true) - isDefault Boolean @default(false) // Standard-Provider - createdAt DateTime @default(now()) - updatedAt DateTime @updatedAt + + // IMAP/SMTP-Server für E-Mail-Client (optional, default: mail.{domain}) + imapServer String? // z.B. "mail.stressfrei-wechseln.de" + imapPort Int? @default(993) + smtpServer String? + smtpPort Int? @default(465) + + // Verschlüsselungs-Einstellungen + imapEncryption MailEncryption @default(SSL) // SSL, STARTTLS oder NONE + smtpEncryption MailEncryption @default(SSL) // SSL, STARTTLS oder NONE + allowSelfSignedCerts Boolean @default(false) // Selbstsignierte Zertifikate erlauben + + isActive Boolean @default(true) + isDefault Boolean @default(false) // Standard-Provider + createdAt DateTime @default(now()) + updatedAt DateTime @updatedAt } // ==================== STRESSFREI-WECHSELN EMAIL ADDRESSES ==================== model StressfreiEmail { - id Int @id @default(autoincrement()) + id Int @id @default(autoincrement()) customerId Int - customer Customer @relation(fields: [customerId], references: [id], onDelete: Cascade) + customer Customer @relation(fields: [customerId], references: [id], onDelete: Cascade) email String // Die Weiterleitungs-E-Mail-Adresse platform String? // Für welche Plattform (z.B. "Freenet", "Klarmobil") - notes String? @db.Text // Optionale Notizen - isActive Boolean @default(true) - isProvisioned Boolean @default(false) // Wurde bei Provider angelegt? + notes String? @db.Text // Optionale Notizen + isActive Boolean @default(true) + isProvisioned Boolean @default(false) // Wurde bei Provider angelegt? provisionedAt DateTime? // Wann wurde provisioniert? - provisionError String? @db.Text // Fehlermeldung falls Provisionierung fehlschlug - contracts Contract[] // Verträge die diese E-Mail als Benutzername verwenden - createdAt DateTime @default(now()) - updatedAt DateTime @updatedAt + provisionError String? @db.Text // Fehlermeldung falls Provisionierung fehlschlug + + // Mailbox-Zugangsdaten (für IMAP/SMTP-Zugang) + hasMailbox Boolean @default(false) // Hat echte Mailbox (nicht nur Weiterleitung)? + emailPasswordEncrypted String? // Verschlüsseltes Mailbox-Passwort (AES-256-GCM) + + contracts Contract[] // Verträge die diese E-Mail als Benutzername verwenden + cachedEmails CachedEmail[] // Gecachte E-Mails aus dieser Mailbox + createdAt DateTime @default(now()) + updatedAt DateTime @updatedAt +} + +// ==================== CACHED EMAILS (E-Mail-Client) ==================== + +enum EmailFolder { + INBOX + SENT +} + +model CachedEmail { + id Int @id @default(autoincrement()) + stressfreiEmailId Int + stressfreiEmail StressfreiEmail @relation(fields: [stressfreiEmailId], references: [id], onDelete: Cascade) + + // Ordner (Posteingang oder Gesendet) + folder EmailFolder @default(INBOX) + + // IMAP-Identifikation + messageId String // RFC 5322 Message-ID + uid Int // IMAP UID (für Synchronisierung, bei SENT = 0) + + // E-Mail-Metadaten + subject String? + fromAddress String + fromName String? + toAddresses String @db.Text // JSON Array + ccAddresses String? @db.Text // JSON Array + receivedAt DateTime + + // Inhalt + textBody String? @db.LongText + htmlBody String? @db.LongText + hasAttachments Boolean @default(false) + attachmentNames String? @db.Text // JSON Array + + // Vertragszuordnung + contractId Int? + contract Contract? @relation(fields: [contractId], references: [id], onDelete: SetNull) + assignedAt DateTime? + assignedBy Int? // User ID der die Zuordnung gemacht hat + isAutoAssigned Boolean @default(false) // true = automatisch beim Senden aus Vertrag + + // Flags + isRead Boolean @default(false) + isStarred Boolean @default(false) + + // Papierkorb + isDeleted Boolean @default(false) // Im Papierkorb? + deletedAt DateTime? // Wann gelöscht? + + createdAt DateTime @default(now()) + updatedAt DateTime @updatedAt + + @@unique([stressfreiEmailId, messageId, folder]) // Folder hinzugefügt: gleiche MessageID kann in INBOX und SENT existieren + @@index([contractId]) + @@index([stressfreiEmailId, folder, receivedAt]) + @@index([stressfreiEmailId, isDeleted]) // Für Papierkorb-Abfragen } // ==================== METERS (Energy) ==================== @@ -464,7 +547,8 @@ model Contract { tvDetails TvContractDetails? carInsuranceDetails CarInsuranceDetails? - tasks ContractTask[] + tasks ContractTask[] + assignedEmails CachedEmail[] // Zugeordnete E-Mails aus dem E-Mail-Client createdAt DateTime @default(now()) updatedAt DateTime @updatedAt diff --git a/backend/node_modules/.prisma/client/wasm.js b/backend/node_modules/.prisma/client/wasm.js index 788cdf87..f2d10b1d 100644 --- a/backend/node_modules/.prisma/client/wasm.js +++ b/backend/node_modules/.prisma/client/wasm.js @@ -137,6 +137,7 @@ exports.Prisma.UserScalarFieldEnum = { firstName: 'firstName', lastName: 'lastName', isActive: 'isActive', + tokenInvalidatedAt: 'tokenInvalidatedAt', customerId: 'customerId', createdAt: 'createdAt', updatedAt: 'updatedAt' @@ -259,6 +260,13 @@ exports.Prisma.EmailProviderConfigScalarFieldEnum = { passwordEncrypted: 'passwordEncrypted', domain: 'domain', defaultForwardEmail: 'defaultForwardEmail', + imapServer: 'imapServer', + imapPort: 'imapPort', + smtpServer: 'smtpServer', + smtpPort: 'smtpPort', + imapEncryption: 'imapEncryption', + smtpEncryption: 'smtpEncryption', + allowSelfSignedCerts: 'allowSelfSignedCerts', isActive: 'isActive', isDefault: 'isDefault', createdAt: 'createdAt', @@ -275,6 +283,36 @@ exports.Prisma.StressfreiEmailScalarFieldEnum = { isProvisioned: 'isProvisioned', provisionedAt: 'provisionedAt', provisionError: 'provisionError', + hasMailbox: 'hasMailbox', + emailPasswordEncrypted: 'emailPasswordEncrypted', + createdAt: 'createdAt', + updatedAt: 'updatedAt' +}; + +exports.Prisma.CachedEmailScalarFieldEnum = { + id: 'id', + stressfreiEmailId: 'stressfreiEmailId', + folder: 'folder', + messageId: 'messageId', + uid: 'uid', + subject: 'subject', + fromAddress: 'fromAddress', + fromName: 'fromName', + toAddresses: 'toAddresses', + ccAddresses: 'ccAddresses', + receivedAt: 'receivedAt', + textBody: 'textBody', + htmlBody: 'htmlBody', + hasAttachments: 'hasAttachments', + attachmentNames: 'attachmentNames', + contractId: 'contractId', + assignedAt: 'assignedAt', + assignedBy: 'assignedBy', + isAutoAssigned: 'isAutoAssigned', + isRead: 'isRead', + isStarred: 'isStarred', + isDeleted: 'isDeleted', + deletedAt: 'deletedAt', createdAt: 'createdAt', updatedAt: 'updatedAt' }; @@ -542,6 +580,17 @@ exports.EmailProviderType = exports.$Enums.EmailProviderType = { DIRECTADMIN: 'DIRECTADMIN' }; +exports.MailEncryption = exports.$Enums.MailEncryption = { + SSL: 'SSL', + STARTTLS: 'STARTTLS', + NONE: 'NONE' +}; + +exports.EmailFolder = exports.$Enums.EmailFolder = { + INBOX: 'INBOX', + SENT: 'SENT' +}; + exports.MeterType = exports.$Enums.MeterType = { ELECTRICITY: 'ELECTRICITY', GAS: 'GAS' @@ -592,6 +641,7 @@ exports.Prisma.ModelName = { IdentityDocument: 'IdentityDocument', EmailProviderConfig: 'EmailProviderConfig', StressfreiEmail: 'StressfreiEmail', + CachedEmail: 'CachedEmail', Meter: 'Meter', MeterReading: 'MeterReading', SalesPlatform: 'SalesPlatform', diff --git a/backend/package-lock.json b/backend/package-lock.json index 9a1c3772..40d90ed1 100644 --- a/backend/package-lock.json +++ b/backend/package-lock.json @@ -9,22 +9,31 @@ "version": "1.0.0", "dependencies": { "@prisma/client": "^5.22.0", + "adm-zip": "^0.5.16", + "archiver": "^7.0.1", "bcryptjs": "^2.4.3", "cors": "^2.8.5", "dotenv": "^16.4.5", "express": "^4.21.1", "express-validator": "^7.2.0", + "imapflow": "^1.2.8", "jsonwebtoken": "^9.0.2", + "mailparser": "^3.9.3", "multer": "^1.4.5-lts.1", + "nodemailer": "^7.0.13", "undici": "^6.23.0" }, "devDependencies": { + "@types/adm-zip": "^0.5.7", + "@types/archiver": "^7.0.0", "@types/bcryptjs": "^2.4.6", "@types/cors": "^2.8.17", "@types/express": "^4.17.25", "@types/jsonwebtoken": "^9.0.7", + "@types/mailparser": "^3.4.6", "@types/multer": "^1.4.12", "@types/node": "^22.9.0", + "@types/nodemailer": "^7.0.9", "prisma": "^5.22.0", "tsx": "^4.19.2", "typescript": "^5.6.3" @@ -446,6 +455,36 @@ "node": ">=18" } }, + "node_modules/@isaacs/cliui": { + "version": "8.0.2", + "resolved": "https://registry.npmjs.org/@isaacs/cliui/-/cliui-8.0.2.tgz", + "integrity": "sha512-O8jcjabXaleOG9DQ0+ARXWZBTfnP4WNAqzuiJK7ll44AmxGKv/J2M4TPjxjY3znBCfvBXFzucm1twdyFybFqEA==", + "dependencies": { + "string-width": "^5.1.2", + "string-width-cjs": "npm:string-width@^4.2.0", + "strip-ansi": "^7.0.1", + "strip-ansi-cjs": "npm:strip-ansi@^6.0.1", + "wrap-ansi": "^8.1.0", + "wrap-ansi-cjs": "npm:wrap-ansi@^7.0.0" + }, + "engines": { + "node": ">=12" + } + }, + "node_modules/@pinojs/redact": { + "version": "0.4.0", + "resolved": "https://registry.npmjs.org/@pinojs/redact/-/redact-0.4.0.tgz", + "integrity": "sha512-k2ENnmBugE/rzQfEcdWHcCY+/FM3VLzH9cYEsbdsoqrvzAKRhUZeRNhAZvB8OitQJ1TBed3yqWtdjzS6wJKBwg==" + }, + "node_modules/@pkgjs/parseargs": { + "version": "0.11.0", + "resolved": "https://registry.npmjs.org/@pkgjs/parseargs/-/parseargs-0.11.0.tgz", + "integrity": "sha512-+1VkjdD0QBLPodGrJUeqarH8VAIvQODIbwh9XpP5Syisf7YoQgsJKPNFoqqLQlu+VQ/tVSshMR6loPMn8U+dPg==", + "optional": true, + "engines": { + "node": ">=14" + } + }, "node_modules/@prisma/client": { "version": "5.22.0", "resolved": "https://registry.npmjs.org/@prisma/client/-/client-5.22.0.tgz", @@ -508,6 +547,36 @@ "@prisma/debug": "5.22.0" } }, + "node_modules/@selderee/plugin-htmlparser2": { + "version": "0.11.0", + "resolved": "https://registry.npmjs.org/@selderee/plugin-htmlparser2/-/plugin-htmlparser2-0.11.0.tgz", + "integrity": "sha512-P33hHGdldxGabLFjPPpaTxVolMrzrcegejx+0GxjrIb9Zv48D8yAIA/QTDR2dFl7Uz7urX8aX6+5bCZslr+gWQ==", + "dependencies": { + "domhandler": "^5.0.3", + "selderee": "^0.11.0" + }, + "funding": { + "url": "https://ko-fi.com/killymxi" + } + }, + "node_modules/@types/adm-zip": { + "version": "0.5.7", + "resolved": "https://registry.npmjs.org/@types/adm-zip/-/adm-zip-0.5.7.tgz", + "integrity": "sha512-DNEs/QvmyRLurdQPChqq0Md4zGvPwHerAJYWk9l2jCbD1VPpnzRJorOdiq4zsw09NFbYnhfsoEhWtxIzXpn2yw==", + "dev": true, + "dependencies": { + "@types/node": "*" + } + }, + "node_modules/@types/archiver": { + "version": "7.0.0", + "resolved": "https://registry.npmjs.org/@types/archiver/-/archiver-7.0.0.tgz", + "integrity": "sha512-/3vwGwx9n+mCQdYZ2IKGGHEFL30I96UgBlk8EtRDDFQ9uxM1l4O5Ci6r00EMAkiDaTqD9DQ6nVrWRICnBPtzzg==", + "dev": true, + "dependencies": { + "@types/readdir-glob": "*" + } + }, "node_modules/@types/bcryptjs": { "version": "2.4.6", "resolved": "https://registry.npmjs.org/@types/bcryptjs/-/bcryptjs-2.4.6.tgz", @@ -582,6 +651,28 @@ "@types/node": "*" } }, + "node_modules/@types/mailparser": { + "version": "3.4.6", + "resolved": "https://registry.npmjs.org/@types/mailparser/-/mailparser-3.4.6.tgz", + "integrity": "sha512-wVV3cnIKzxTffaPH8iRnddX1zahbYB1ZEoAxyhoBo3TBCBuK6nZ8M8JYO/RhsCuuBVOw/DEN/t/ENbruwlxn6Q==", + "dev": true, + "dependencies": { + "@types/node": "*", + "iconv-lite": "^0.6.3" + } + }, + "node_modules/@types/mailparser/node_modules/iconv-lite": { + "version": "0.6.3", + "resolved": "https://registry.npmjs.org/iconv-lite/-/iconv-lite-0.6.3.tgz", + "integrity": "sha512-4fCk79wshMdzMp2rH06qWrJE4iolqLhCUH+OiuIgU++RB0+94NlDL81atO7GX55uUKueo0txHNtvEyI6D7WdMw==", + "dev": true, + "dependencies": { + "safer-buffer": ">= 2.1.2 < 3.0.0" + }, + "engines": { + "node": ">=0.10.0" + } + }, "node_modules/@types/mime": { "version": "1.3.5", "resolved": "https://registry.npmjs.org/@types/mime/-/mime-1.3.5.tgz", @@ -612,6 +703,15 @@ "undici-types": "~6.21.0" } }, + "node_modules/@types/nodemailer": { + "version": "7.0.9", + "resolved": "https://registry.npmjs.org/@types/nodemailer/-/nodemailer-7.0.9.tgz", + "integrity": "sha512-vI8oF1M+8JvQhsId0Pc38BdUP2evenIIys7c7p+9OZXSPOH5c1dyINP1jT8xQ2xPuBUXmIC87s+91IZMDjH8Ow==", + "dev": true, + "dependencies": { + "@types/node": "*" + } + }, "node_modules/@types/qs": { "version": "6.14.0", "resolved": "https://registry.npmjs.org/@types/qs/-/qs-6.14.0.tgz", @@ -624,6 +724,15 @@ "integrity": "sha512-hKormJbkJqzQGhziax5PItDUTMAM9uE2XXQmM37dyd4hVM+5aVl7oVxMVUiVQn2oCQFN/LKCZdvSM0pFRqbSmQ==", "dev": true }, + "node_modules/@types/readdir-glob": { + "version": "1.1.5", + "resolved": "https://registry.npmjs.org/@types/readdir-glob/-/readdir-glob-1.1.5.tgz", + "integrity": "sha512-raiuEPUYqXu+nvtY2Pe8s8FEmZ3x5yAH4VkLdihcPdalvsHltomrRC9BzuStrJ9yk06470hS0Crw0f1pXqD+Hg==", + "dev": true, + "dependencies": { + "@types/node": "*" + } + }, "node_modules/@types/send": { "version": "1.2.1", "resolved": "https://registry.npmjs.org/@types/send/-/send-1.2.1.tgz", @@ -654,6 +763,27 @@ "@types/node": "*" } }, + "node_modules/@zone-eu/mailsplit": { + "version": "5.4.8", + "resolved": "https://registry.npmjs.org/@zone-eu/mailsplit/-/mailsplit-5.4.8.tgz", + "integrity": "sha512-eEyACj4JZ7sjzRvy26QhLgKEMWwQbsw1+QZnlLX+/gihcNH07lVPOcnwf5U6UAL7gkc//J3jVd76o/WS+taUiA==", + "dependencies": { + "libbase64": "1.3.0", + "libmime": "5.3.7", + "libqp": "2.1.1" + } + }, + "node_modules/abort-controller": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/abort-controller/-/abort-controller-3.0.0.tgz", + "integrity": "sha512-h8lQ8tacZYnR3vNQTgibj+tODHI5/+l06Au2Pcriv/Gmet0eaj4TwWH41sO9wnHDiQsEj19q0drzdWdeAHtweg==", + "dependencies": { + "event-target-shim": "^5.0.0" + }, + "engines": { + "node": ">=6.5" + } + }, "node_modules/accepts": { "version": "1.3.8", "resolved": "https://registry.npmjs.org/accepts/-/accepts-1.3.8.tgz", @@ -666,16 +796,189 @@ "node": ">= 0.6" } }, + "node_modules/adm-zip": { + "version": "0.5.16", + "resolved": "https://registry.npmjs.org/adm-zip/-/adm-zip-0.5.16.tgz", + "integrity": "sha512-TGw5yVi4saajsSEgz25grObGHEUaDrniwvA2qwSC060KfqGPdglhvPMA2lPIoxs3PQIItj2iag35fONcQqgUaQ==", + "engines": { + "node": ">=12.0" + } + }, + "node_modules/ansi-regex": { + "version": "6.2.2", + "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-6.2.2.tgz", + "integrity": "sha512-Bq3SmSpyFHaWjPk8If9yc6svM8c56dB5BAtW4Qbw5jHTwwXXcTLoRMkpDJp6VL0XzlWaCHTXrkFURMYmD0sLqg==", + "engines": { + "node": ">=12" + }, + "funding": { + "url": "https://github.com/chalk/ansi-regex?sponsor=1" + } + }, + "node_modules/ansi-styles": { + "version": "6.2.3", + "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-6.2.3.tgz", + "integrity": "sha512-4Dj6M28JB+oAH8kFkTLUo+a2jwOFkuqb3yucU0CANcRRUbxS0cP0nZYCGjcc3BNXwRIsUVmDGgzawme7zvJHvg==", + "engines": { + "node": ">=12" + }, + "funding": { + "url": "https://github.com/chalk/ansi-styles?sponsor=1" + } + }, "node_modules/append-field": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/append-field/-/append-field-1.0.0.tgz", "integrity": "sha512-klpgFSWLW1ZEs8svjfb7g4qWY0YS5imI82dTg+QahUvJ8YqAY0P10Uk8tTyh9ZGuYEZEMaeJYCF5BFuX552hsw==" }, + "node_modules/archiver": { + "version": "7.0.1", + "resolved": "https://registry.npmjs.org/archiver/-/archiver-7.0.1.tgz", + "integrity": "sha512-ZcbTaIqJOfCc03QwD468Unz/5Ir8ATtvAHsK+FdXbDIbGfihqh9mrvdcYunQzqn4HrvWWaFyaxJhGZagaJJpPQ==", + "dependencies": { + "archiver-utils": "^5.0.2", + "async": "^3.2.4", + "buffer-crc32": "^1.0.0", + "readable-stream": "^4.0.0", + "readdir-glob": "^1.1.2", + "tar-stream": "^3.0.0", + "zip-stream": "^6.0.1" + }, + "engines": { + "node": ">= 14" + } + }, + "node_modules/archiver-utils": { + "version": "5.0.2", + "resolved": "https://registry.npmjs.org/archiver-utils/-/archiver-utils-5.0.2.tgz", + "integrity": "sha512-wuLJMmIBQYCsGZgYLTy5FIB2pF6Lfb6cXMSF8Qywwk3t20zWnAi7zLcQFdKQmIB8wyZpY5ER38x08GbwtR2cLA==", + "dependencies": { + "glob": "^10.0.0", + "graceful-fs": "^4.2.0", + "is-stream": "^2.0.1", + "lazystream": "^1.0.0", + "lodash": "^4.17.15", + "normalize-path": "^3.0.0", + "readable-stream": "^4.0.0" + }, + "engines": { + "node": ">= 14" + } + }, + "node_modules/archiver-utils/node_modules/readable-stream": { + "version": "4.7.0", + "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-4.7.0.tgz", + "integrity": "sha512-oIGGmcpTLwPga8Bn6/Z75SVaH1z5dUut2ibSyAMVhmUggWpmDn2dapB0n7f8nwaSiRtepAsfJyfXIO5DCVAODg==", + "dependencies": { + "abort-controller": "^3.0.0", + "buffer": "^6.0.3", + "events": "^3.3.0", + "process": "^0.11.10", + "string_decoder": "^1.3.0" + }, + "engines": { + "node": "^12.22.0 || ^14.17.0 || >=16.0.0" + } + }, + "node_modules/archiver-utils/node_modules/string_decoder": { + "version": "1.3.0", + "resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-1.3.0.tgz", + "integrity": "sha512-hkRX8U1WjJFd8LsDJ2yQ/wWWxaopEsABU1XfkM8A+j0+85JAGppt16cr1Whg6KIbb4okU6Mql6BOj+uup/wKeA==", + "dependencies": { + "safe-buffer": "~5.2.0" + } + }, + "node_modules/archiver/node_modules/readable-stream": { + "version": "4.7.0", + "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-4.7.0.tgz", + "integrity": "sha512-oIGGmcpTLwPga8Bn6/Z75SVaH1z5dUut2ibSyAMVhmUggWpmDn2dapB0n7f8nwaSiRtepAsfJyfXIO5DCVAODg==", + "dependencies": { + "abort-controller": "^3.0.0", + "buffer": "^6.0.3", + "events": "^3.3.0", + "process": "^0.11.10", + "string_decoder": "^1.3.0" + }, + "engines": { + "node": "^12.22.0 || ^14.17.0 || >=16.0.0" + } + }, + "node_modules/archiver/node_modules/string_decoder": { + "version": "1.3.0", + "resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-1.3.0.tgz", + "integrity": "sha512-hkRX8U1WjJFd8LsDJ2yQ/wWWxaopEsABU1XfkM8A+j0+85JAGppt16cr1Whg6KIbb4okU6Mql6BOj+uup/wKeA==", + "dependencies": { + "safe-buffer": "~5.2.0" + } + }, "node_modules/array-flatten": { "version": "1.1.1", "resolved": "https://registry.npmjs.org/array-flatten/-/array-flatten-1.1.1.tgz", "integrity": "sha512-PCVAQswWemu6UdxsDFFX/+gVeYqKAod3D3UVm91jHwynguOwAvYPhx8nNlM++NqRcK6CxxpUafjmhIdKiHibqg==" }, + "node_modules/async": { + "version": "3.2.6", + "resolved": "https://registry.npmjs.org/async/-/async-3.2.6.tgz", + "integrity": "sha512-htCUDlxyyCLMgaM3xXg0C0LW2xqfuQ6p05pCEIsXuyQ+a1koYKTuBMzRNwmybfLgvJDMd0r1LTn4+E0Ti6C2AA==" + }, + "node_modules/atomic-sleep": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/atomic-sleep/-/atomic-sleep-1.0.0.tgz", + "integrity": "sha512-kNOjDqAh7px0XWNI+4QbzoiR/nTkHAWNud2uvnJquD1/x5a7EQZMJT0AczqK0Qn67oY/TTQ1LbUKajZpp3I9tQ==", + "engines": { + "node": ">=8.0.0" + } + }, + "node_modules/b4a": { + "version": "1.7.3", + "resolved": "https://registry.npmjs.org/b4a/-/b4a-1.7.3.tgz", + "integrity": "sha512-5Q2mfq2WfGuFp3uS//0s6baOJLMoVduPYVeNmDYxu5OUA1/cBfvr2RIS7vi62LdNj/urk1hfmj867I3qt6uZ7Q==", + "peerDependencies": { + "react-native-b4a": "*" + }, + "peerDependenciesMeta": { + "react-native-b4a": { + "optional": true + } + } + }, + "node_modules/balanced-match": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/balanced-match/-/balanced-match-1.0.2.tgz", + "integrity": "sha512-3oSeUO0TMV67hN1AmbXsK4yaqU7tjiHlbxRDZOpH0KW9+CeX4bRAaX0Anxt0tx2MrpRpWwQaPwIlISEJhYU5Pw==" + }, + "node_modules/bare-events": { + "version": "2.8.2", + "resolved": "https://registry.npmjs.org/bare-events/-/bare-events-2.8.2.tgz", + "integrity": "sha512-riJjyv1/mHLIPX4RwiK+oW9/4c3TEUeORHKefKAKnZ5kyslbN+HXowtbaVEqt4IMUB7OXlfixcs6gsFeo/jhiQ==", + "peerDependencies": { + "bare-abort-controller": "*" + }, + "peerDependenciesMeta": { + "bare-abort-controller": { + "optional": true + } + } + }, + "node_modules/base64-js": { + "version": "1.5.1", + "resolved": "https://registry.npmjs.org/base64-js/-/base64-js-1.5.1.tgz", + "integrity": "sha512-AKpaYlHn8t4SVbOHCy+b5+KKgvR4vrsD8vbvrbiQJps7fKDTkjkDry6ji0rUJjC0kzbNePLwzxq8iypo41qeWA==", + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/feross" + }, + { + "type": "patreon", + "url": "https://www.patreon.com/feross" + }, + { + "type": "consulting", + "url": "https://feross.org/support" + } + ] + }, "node_modules/bcryptjs": { "version": "2.4.3", "resolved": "https://registry.npmjs.org/bcryptjs/-/bcryptjs-2.4.3.tgz", @@ -704,6 +1007,45 @@ "npm": "1.2.8000 || >= 1.4.16" } }, + "node_modules/brace-expansion": { + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-2.0.2.tgz", + "integrity": "sha512-Jt0vHyM+jmUBqojB7E1NIYadt0vI0Qxjxd2TErW94wDz+E2LAm5vKMXXwg6ZZBTHPuUlDgQHKXvjGBdfcF1ZDQ==", + "dependencies": { + "balanced-match": "^1.0.0" + } + }, + "node_modules/buffer": { + "version": "6.0.3", + "resolved": "https://registry.npmjs.org/buffer/-/buffer-6.0.3.tgz", + "integrity": "sha512-FTiCpNxtwiZZHEZbcbTIcZjERVICn9yq/pDFkTl95/AxzD1naBctN7YO68riM/gLSDY7sdrMby8hofADYuuqOA==", + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/feross" + }, + { + "type": "patreon", + "url": "https://www.patreon.com/feross" + }, + { + "type": "consulting", + "url": "https://feross.org/support" + } + ], + "dependencies": { + "base64-js": "^1.3.1", + "ieee754": "^1.2.1" + } + }, + "node_modules/buffer-crc32": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/buffer-crc32/-/buffer-crc32-1.0.0.tgz", + "integrity": "sha512-Db1SbgBS/fg/392AblrMJk97KggmvYhr4pB5ZIMTWtaivCPMWLkmb7m21cJvpvgK+J3nsU2CmmixNBZx4vFj/w==", + "engines": { + "node": ">=8.0.0" + } + }, "node_modules/buffer-equal-constant-time": { "version": "1.0.1", "resolved": "https://registry.npmjs.org/buffer-equal-constant-time/-/buffer-equal-constant-time-1.0.1.tgz", @@ -760,6 +1102,60 @@ "url": "https://github.com/sponsors/ljharb" } }, + "node_modules/color-convert": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-2.0.1.tgz", + "integrity": "sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ==", + "dependencies": { + "color-name": "~1.1.4" + }, + "engines": { + "node": ">=7.0.0" + } + }, + "node_modules/color-name": { + "version": "1.1.4", + "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.4.tgz", + "integrity": "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==" + }, + "node_modules/compress-commons": { + "version": "6.0.2", + "resolved": "https://registry.npmjs.org/compress-commons/-/compress-commons-6.0.2.tgz", + "integrity": "sha512-6FqVXeETqWPoGcfzrXb37E50NP0LXT8kAMu5ooZayhWWdgEY4lBEEcbQNXtkuKQsGduxiIcI4gOTsxTmuq/bSg==", + "dependencies": { + "crc-32": "^1.2.0", + "crc32-stream": "^6.0.0", + "is-stream": "^2.0.1", + "normalize-path": "^3.0.0", + "readable-stream": "^4.0.0" + }, + "engines": { + "node": ">= 14" + } + }, + "node_modules/compress-commons/node_modules/readable-stream": { + "version": "4.7.0", + "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-4.7.0.tgz", + "integrity": "sha512-oIGGmcpTLwPga8Bn6/Z75SVaH1z5dUut2ibSyAMVhmUggWpmDn2dapB0n7f8nwaSiRtepAsfJyfXIO5DCVAODg==", + "dependencies": { + "abort-controller": "^3.0.0", + "buffer": "^6.0.3", + "events": "^3.3.0", + "process": "^0.11.10", + "string_decoder": "^1.3.0" + }, + "engines": { + "node": "^12.22.0 || ^14.17.0 || >=16.0.0" + } + }, + "node_modules/compress-commons/node_modules/string_decoder": { + "version": "1.3.0", + "resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-1.3.0.tgz", + "integrity": "sha512-hkRX8U1WjJFd8LsDJ2yQ/wWWxaopEsABU1XfkM8A+j0+85JAGppt16cr1Whg6KIbb4okU6Mql6BOj+uup/wKeA==", + "dependencies": { + "safe-buffer": "~5.2.0" + } + }, "node_modules/concat-stream": { "version": "1.6.2", "resolved": "https://registry.npmjs.org/concat-stream/-/concat-stream-1.6.2.tgz", @@ -823,6 +1219,65 @@ "node": ">= 0.10" } }, + "node_modules/crc-32": { + "version": "1.2.2", + "resolved": "https://registry.npmjs.org/crc-32/-/crc-32-1.2.2.tgz", + "integrity": "sha512-ROmzCKrTnOwybPcJApAA6WBWij23HVfGVNKqqrZpuyZOHqK2CwHSvpGuyt/UNNvaIjEd8X5IFGp4Mh+Ie1IHJQ==", + "bin": { + "crc32": "bin/crc32.njs" + }, + "engines": { + "node": ">=0.8" + } + }, + "node_modules/crc32-stream": { + "version": "6.0.0", + "resolved": "https://registry.npmjs.org/crc32-stream/-/crc32-stream-6.0.0.tgz", + "integrity": "sha512-piICUB6ei4IlTv1+653yq5+KoqfBYmj9bw6LqXoOneTMDXk5nM1qt12mFW1caG3LlJXEKW1Bp0WggEmIfQB34g==", + "dependencies": { + "crc-32": "^1.2.0", + "readable-stream": "^4.0.0" + }, + "engines": { + "node": ">= 14" + } + }, + "node_modules/crc32-stream/node_modules/readable-stream": { + "version": "4.7.0", + "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-4.7.0.tgz", + "integrity": "sha512-oIGGmcpTLwPga8Bn6/Z75SVaH1z5dUut2ibSyAMVhmUggWpmDn2dapB0n7f8nwaSiRtepAsfJyfXIO5DCVAODg==", + "dependencies": { + "abort-controller": "^3.0.0", + "buffer": "^6.0.3", + "events": "^3.3.0", + "process": "^0.11.10", + "string_decoder": "^1.3.0" + }, + "engines": { + "node": "^12.22.0 || ^14.17.0 || >=16.0.0" + } + }, + "node_modules/crc32-stream/node_modules/string_decoder": { + "version": "1.3.0", + "resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-1.3.0.tgz", + "integrity": "sha512-hkRX8U1WjJFd8LsDJ2yQ/wWWxaopEsABU1XfkM8A+j0+85JAGppt16cr1Whg6KIbb4okU6Mql6BOj+uup/wKeA==", + "dependencies": { + "safe-buffer": "~5.2.0" + } + }, + "node_modules/cross-spawn": { + "version": "7.0.6", + "resolved": "https://registry.npmjs.org/cross-spawn/-/cross-spawn-7.0.6.tgz", + "integrity": "sha512-uV2QOWP2nWzsy2aMp8aRibhi9dlzF5Hgh5SHaB9OiTGEyDTiJJyx0uy51QXdyWbtAHNua4XJzUKca3OzKUd3vA==", + "dependencies": { + "path-key": "^3.1.0", + "shebang-command": "^2.0.0", + "which": "^2.0.1" + }, + "engines": { + "node": ">= 8" + } + }, "node_modules/debug": { "version": "2.6.9", "resolved": "https://registry.npmjs.org/debug/-/debug-2.6.9.tgz", @@ -831,6 +1286,14 @@ "ms": "2.0.0" } }, + "node_modules/deepmerge": { + "version": "4.3.1", + "resolved": "https://registry.npmjs.org/deepmerge/-/deepmerge-4.3.1.tgz", + "integrity": "sha512-3sUqbMEc77XqpdNO7FRyRog+eW3ph+GYCbj+rK+uYyRMuwsVy0rMiVtPn+QJlKFvWP/1PYpapqYn0Me2knFn+A==", + "engines": { + "node": ">=0.10.0" + } + }, "node_modules/depd": { "version": "2.0.0", "resolved": "https://registry.npmjs.org/depd/-/depd-2.0.0.tgz", @@ -848,6 +1311,57 @@ "npm": "1.2.8000 || >= 1.4.16" } }, + "node_modules/dom-serializer": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/dom-serializer/-/dom-serializer-2.0.0.tgz", + "integrity": "sha512-wIkAryiqt/nV5EQKqQpo3SToSOV9J0DnbJqwK7Wv/Trc92zIAYZ4FlMu+JPFW1DfGFt81ZTCGgDEabffXeLyJg==", + "dependencies": { + "domelementtype": "^2.3.0", + "domhandler": "^5.0.2", + "entities": "^4.2.0" + }, + "funding": { + "url": "https://github.com/cheeriojs/dom-serializer?sponsor=1" + } + }, + "node_modules/domelementtype": { + "version": "2.3.0", + "resolved": "https://registry.npmjs.org/domelementtype/-/domelementtype-2.3.0.tgz", + "integrity": "sha512-OLETBj6w0OsagBwdXnPdN0cnMfF9opN69co+7ZrbfPGrdpPVNBUj02spi6B1N7wChLQiPn4CSH/zJvXw56gmHw==", + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/fb55" + } + ] + }, + "node_modules/domhandler": { + "version": "5.0.3", + "resolved": "https://registry.npmjs.org/domhandler/-/domhandler-5.0.3.tgz", + "integrity": "sha512-cgwlv/1iFQiFnU96XXgROh8xTeetsnJiDsTc7TYCLFd9+/WNkIqPTxiM/8pSd8VIrhXGTf1Ny1q1hquVqDJB5w==", + "dependencies": { + "domelementtype": "^2.3.0" + }, + "engines": { + "node": ">= 4" + }, + "funding": { + "url": "https://github.com/fb55/domhandler?sponsor=1" + } + }, + "node_modules/domutils": { + "version": "3.2.2", + "resolved": "https://registry.npmjs.org/domutils/-/domutils-3.2.2.tgz", + "integrity": "sha512-6kZKyUajlDuqlHKVX1w7gyslj9MPIXzIFiz/rGu35uC1wMi+kMhQwGhl4lt9unC9Vb9INnY9Z3/ZA3+FhASLaw==", + "dependencies": { + "dom-serializer": "^2.0.0", + "domelementtype": "^2.3.0", + "domhandler": "^5.0.3" + }, + "funding": { + "url": "https://github.com/fb55/domutils?sponsor=1" + } + }, "node_modules/dotenv": { "version": "16.6.1", "resolved": "https://registry.npmjs.org/dotenv/-/dotenv-16.6.1.tgz", @@ -872,6 +1386,11 @@ "node": ">= 0.4" } }, + "node_modules/eastasianwidth": { + "version": "0.2.0", + "resolved": "https://registry.npmjs.org/eastasianwidth/-/eastasianwidth-0.2.0.tgz", + "integrity": "sha512-I88TYZWc9XiYHRQ4/3c5rjjfgkjhLyW2luGIheGERbNQ6OY7yTybanSpDXZa8y7VUP9YmDcYa+eyq4ca7iLqWA==" + }, "node_modules/ecdsa-sig-formatter": { "version": "1.0.11", "resolved": "https://registry.npmjs.org/ecdsa-sig-formatter/-/ecdsa-sig-formatter-1.0.11.tgz", @@ -885,6 +1404,11 @@ "resolved": "https://registry.npmjs.org/ee-first/-/ee-first-1.1.1.tgz", "integrity": "sha512-WMwm9LhRUo+WUaRN+vRuETqG89IgZphVSNkdFgeb6sS/E4OrDIN7t48CAewSHXc6C8lefD8KKfr5vY61brQlow==" }, + "node_modules/emoji-regex": { + "version": "9.2.2", + "resolved": "https://registry.npmjs.org/emoji-regex/-/emoji-regex-9.2.2.tgz", + "integrity": "sha512-L18DaJsXSUk2+42pv8mLs5jJT2hqFkFE4j21wOmgbUqsZ2hL72NsUU785g9RXgo3s0ZNgVl42TiHp3ZtOv/Vyg==" + }, "node_modules/encodeurl": { "version": "2.0.0", "resolved": "https://registry.npmjs.org/encodeurl/-/encodeurl-2.0.0.tgz", @@ -893,6 +1417,25 @@ "node": ">= 0.8" } }, + "node_modules/encoding-japanese": { + "version": "2.2.0", + "resolved": "https://registry.npmjs.org/encoding-japanese/-/encoding-japanese-2.2.0.tgz", + "integrity": "sha512-EuJWwlHPZ1LbADuKTClvHtwbaFn4rOD+dRAbWysqEOXRc2Uui0hJInNJrsdH0c+OhJA4nrCBdSkW4DD5YxAo6A==", + "engines": { + "node": ">=8.10.0" + } + }, + "node_modules/entities": { + "version": "4.5.0", + "resolved": "https://registry.npmjs.org/entities/-/entities-4.5.0.tgz", + "integrity": "sha512-V0hjH4dGPh9Ao5p0MoRY6BVqtwCjhz6vI5LT8AJ55H+4g9/4vbHx1I54fS0XuclLhDHArPQCiMjDxjaL8fPxhw==", + "engines": { + "node": ">=0.12" + }, + "funding": { + "url": "https://github.com/fb55/entities?sponsor=1" + } + }, "node_modules/es-define-property": { "version": "1.0.1", "resolved": "https://registry.npmjs.org/es-define-property/-/es-define-property-1.0.1.tgz", @@ -974,6 +1517,30 @@ "node": ">= 0.6" } }, + "node_modules/event-target-shim": { + "version": "5.0.1", + "resolved": "https://registry.npmjs.org/event-target-shim/-/event-target-shim-5.0.1.tgz", + "integrity": "sha512-i/2XbnSz/uxRCU6+NdVJgKWDTM427+MqYbkQzD321DuCQJUqOuJKIA0IM2+W2xtYHdKOmZ4dR6fExsd4SXL+WQ==", + "engines": { + "node": ">=6" + } + }, + "node_modules/events": { + "version": "3.3.0", + "resolved": "https://registry.npmjs.org/events/-/events-3.3.0.tgz", + "integrity": "sha512-mQw+2fkQbALzQ7V0MY0IqdnXNOeTtP4r0lN9z7AAawCXgqea7bDii20AYrIBrFd/Hx0M2Ocz6S111CaFkUcb0Q==", + "engines": { + "node": ">=0.8.x" + } + }, + "node_modules/events-universal": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/events-universal/-/events-universal-1.0.1.tgz", + "integrity": "sha512-LUd5euvbMLpwOF8m6ivPCbhQeSiYVNb8Vs0fQ8QjXo0JTkEHpz8pxdQf0gStltaPpw0Cca8b39KxvK9cfKRiAw==", + "dependencies": { + "bare-events": "^2.7.0" + } + }, "node_modules/express": { "version": "4.22.1", "resolved": "https://registry.npmjs.org/express/-/express-4.22.1.tgz", @@ -1031,6 +1598,11 @@ "node": ">= 8.0.0" } }, + "node_modules/fast-fifo": { + "version": "1.3.2", + "resolved": "https://registry.npmjs.org/fast-fifo/-/fast-fifo-1.3.2.tgz", + "integrity": "sha512-/d9sfos4yxzpwkDkuN7k2SqFKtYNmCTzgfEpz82x34IM9/zc8KGxQoXg1liNC/izpRM/MBdt44Nmx41ZWqk+FQ==" + }, "node_modules/finalhandler": { "version": "1.3.2", "resolved": "https://registry.npmjs.org/finalhandler/-/finalhandler-1.3.2.tgz", @@ -1048,6 +1620,21 @@ "node": ">= 0.8" } }, + "node_modules/foreground-child": { + "version": "3.3.1", + "resolved": "https://registry.npmjs.org/foreground-child/-/foreground-child-3.3.1.tgz", + "integrity": "sha512-gIXjKqtFuWEgzFRJA9WCQeSJLZDjgJUOMCMzxtvFq/37KojM1BFGufqsCy0r4qSQmYLsZYMeyRqzIWOMup03sw==", + "dependencies": { + "cross-spawn": "^7.0.6", + "signal-exit": "^4.0.1" + }, + "engines": { + "node": ">=14" + }, + "funding": { + "url": "https://github.com/sponsors/isaacs" + } + }, "node_modules/forwarded": { "version": "0.2.0", "resolved": "https://registry.npmjs.org/forwarded/-/forwarded-0.2.0.tgz", @@ -1133,6 +1720,25 @@ "url": "https://github.com/privatenumber/get-tsconfig?sponsor=1" } }, + "node_modules/glob": { + "version": "10.5.0", + "resolved": "https://registry.npmjs.org/glob/-/glob-10.5.0.tgz", + "integrity": "sha512-DfXN8DfhJ7NH3Oe7cFmu3NCu1wKbkReJ8TorzSAFbSKrlNaQSKfIzqYqVY8zlbs2NLBbWpRiU52GX2PbaBVNkg==", + "dependencies": { + "foreground-child": "^3.1.0", + "jackspeak": "^3.1.2", + "minimatch": "^9.0.4", + "minipass": "^7.1.2", + "package-json-from-dist": "^1.0.0", + "path-scurry": "^1.11.1" + }, + "bin": { + "glob": "dist/esm/bin.mjs" + }, + "funding": { + "url": "https://github.com/sponsors/isaacs" + } + }, "node_modules/gopd": { "version": "1.2.0", "resolved": "https://registry.npmjs.org/gopd/-/gopd-1.2.0.tgz", @@ -1144,6 +1750,11 @@ "url": "https://github.com/sponsors/ljharb" } }, + "node_modules/graceful-fs": { + "version": "4.2.11", + "resolved": "https://registry.npmjs.org/graceful-fs/-/graceful-fs-4.2.11.tgz", + "integrity": "sha512-RbJ5/jmFcNNCcDV5o9eTnBLJ/HszWV0P73bc+Ff4nS/rJj+YaS6IGyiOL0VoBYX+l1Wrl3k63h/KrH+nhJ0XvQ==" + }, "node_modules/has-symbols": { "version": "1.1.0", "resolved": "https://registry.npmjs.org/has-symbols/-/has-symbols-1.1.0.tgz", @@ -1166,6 +1777,47 @@ "node": ">= 0.4" } }, + "node_modules/he": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/he/-/he-1.2.0.tgz", + "integrity": "sha512-F/1DnUGPopORZi0ni+CvrCgHQ5FyEAHRLSApuYWMmrbSwoN2Mn/7k+Gl38gJnR7yyDZk6WLXwiGod1JOWNDKGw==", + "bin": { + "he": "bin/he" + } + }, + "node_modules/html-to-text": { + "version": "9.0.5", + "resolved": "https://registry.npmjs.org/html-to-text/-/html-to-text-9.0.5.tgz", + "integrity": "sha512-qY60FjREgVZL03vJU6IfMV4GDjGBIoOyvuFdpBDIX9yTlDw0TjxVBQp+P8NvpdIXNJvfWBTNul7fsAQJq2FNpg==", + "dependencies": { + "@selderee/plugin-htmlparser2": "^0.11.0", + "deepmerge": "^4.3.1", + "dom-serializer": "^2.0.0", + "htmlparser2": "^8.0.2", + "selderee": "^0.11.0" + }, + "engines": { + "node": ">=14" + } + }, + "node_modules/htmlparser2": { + "version": "8.0.2", + "resolved": "https://registry.npmjs.org/htmlparser2/-/htmlparser2-8.0.2.tgz", + "integrity": "sha512-GYdjWKDkbRLkZ5geuHs5NY1puJ+PXwP7+fHPRz06Eirsb9ugf6d8kkXav6ADhcODhFFPMIXyxkxSuMf3D6NCFA==", + "funding": [ + "https://github.com/fb55/htmlparser2?sponsor=1", + { + "type": "github", + "url": "https://github.com/sponsors/fb55" + } + ], + "dependencies": { + "domelementtype": "^2.3.0", + "domhandler": "^5.0.3", + "domutils": "^3.0.1", + "entities": "^4.4.0" + } + }, "node_modules/http-errors": { "version": "2.0.1", "resolved": "https://registry.npmjs.org/http-errors/-/http-errors-2.0.1.tgz", @@ -1196,11 +1848,69 @@ "node": ">=0.10.0" } }, + "node_modules/ieee754": { + "version": "1.2.1", + "resolved": "https://registry.npmjs.org/ieee754/-/ieee754-1.2.1.tgz", + "integrity": "sha512-dcyqhDvX1C46lXZcVqCpK+FtMRQVdIMN6/Df5js2zouUsqG7I6sFxitIC+7KYK29KdXOLHdu9zL4sFnoVQnqaA==", + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/feross" + }, + { + "type": "patreon", + "url": "https://www.patreon.com/feross" + }, + { + "type": "consulting", + "url": "https://feross.org/support" + } + ] + }, + "node_modules/imapflow": { + "version": "1.2.8", + "resolved": "https://registry.npmjs.org/imapflow/-/imapflow-1.2.8.tgz", + "integrity": "sha512-ym7FF2tKOlOzfRvxehs4eLkhjP8Mme3sSp2tcxEbyoeJuJwtEWxaVDv12+DnaMG2LXm0zuQGWZiClq31FLPUNg==", + "dependencies": { + "@zone-eu/mailsplit": "5.4.8", + "encoding-japanese": "2.2.0", + "iconv-lite": "0.7.2", + "libbase64": "1.3.0", + "libmime": "5.3.7", + "libqp": "2.1.1", + "nodemailer": "7.0.13", + "pino": "10.3.0", + "socks": "2.8.7" + } + }, + "node_modules/imapflow/node_modules/iconv-lite": { + "version": "0.7.2", + "resolved": "https://registry.npmjs.org/iconv-lite/-/iconv-lite-0.7.2.tgz", + "integrity": "sha512-im9DjEDQ55s9fL4EYzOAv0yMqmMBSZp6G0VvFyTMPKWxiSBHUj9NW/qqLmXUwXrrM7AvqSlTCfvqRb0cM8yYqw==", + "dependencies": { + "safer-buffer": ">= 2.1.2 < 3.0.0" + }, + "engines": { + "node": ">=0.10.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/express" + } + }, "node_modules/inherits": { "version": "2.0.4", "resolved": "https://registry.npmjs.org/inherits/-/inherits-2.0.4.tgz", "integrity": "sha512-k/vGaX4/Yla3WzyMCvTQOXYeIHvqOKtnqBduzTHpzpQZzAskKMhZ2K+EnBiSM9zGSoIFeMpXKxa4dYeZIQqewQ==" }, + "node_modules/ip-address": { + "version": "10.1.0", + "resolved": "https://registry.npmjs.org/ip-address/-/ip-address-10.1.0.tgz", + "integrity": "sha512-XXADHxXmvT9+CRxhXg56LJovE+bmWnEWB78LB83VZTprKTmaC5QfruXocxzTZ2Kl0DNwKuBdlIhjL8LeY8Sf8Q==", + "engines": { + "node": ">= 12" + } + }, "node_modules/ipaddr.js": { "version": "1.9.1", "resolved": "https://registry.npmjs.org/ipaddr.js/-/ipaddr.js-1.9.1.tgz", @@ -1209,11 +1919,49 @@ "node": ">= 0.10" } }, + "node_modules/is-fullwidth-code-point": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/is-fullwidth-code-point/-/is-fullwidth-code-point-3.0.0.tgz", + "integrity": "sha512-zymm5+u+sCsSWyD9qNaejV3DFvhCKclKdizYaJUuHA83RLjb7nSuGnddCHGv0hk+KY7BMAlsWeK4Ueg6EV6XQg==", + "engines": { + "node": ">=8" + } + }, + "node_modules/is-stream": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/is-stream/-/is-stream-2.0.1.tgz", + "integrity": "sha512-hFoiJiTl63nn+kstHGBtewWSKnQLpyb155KHheA1l39uvtO9nWIop1p3udqPcUd/xbF1VLMO4n7OI6p7RbngDg==", + "engines": { + "node": ">=8" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, "node_modules/isarray": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/isarray/-/isarray-1.0.0.tgz", "integrity": "sha512-VLghIWNM6ELQzo7zwmcg0NmTVyWKYjvIeM83yjp0wRDTmUnrM678fQbcKBo6n2CJEF0szoG//ytg+TKla89ALQ==" }, + "node_modules/isexe": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/isexe/-/isexe-2.0.0.tgz", + "integrity": "sha512-RHxMLp9lnKHGHRng9QFhRCMbYAcVpn69smSGcq3f36xjgVVWThj4qqLbTLlq7Ssj8B+fIQ1EuCEGI2lKsyQeIw==" + }, + "node_modules/jackspeak": { + "version": "3.4.3", + "resolved": "https://registry.npmjs.org/jackspeak/-/jackspeak-3.4.3.tgz", + "integrity": "sha512-OGlZQpz2yfahA/Rd1Y8Cd9SIEsqvXkLVoSw/cgwhnhFMDbsQFeZYoJJ7bIZBS9BcamUW96asq/npPWugM+RQBw==", + "dependencies": { + "@isaacs/cliui": "^8.0.2" + }, + "funding": { + "url": "https://github.com/sponsors/isaacs" + }, + "optionalDependencies": { + "@pkgjs/parseargs": "^0.11.0" + } + }, "node_modules/jsonwebtoken": { "version": "9.0.3", "resolved": "https://registry.npmjs.org/jsonwebtoken/-/jsonwebtoken-9.0.3.tgz", @@ -1259,6 +2007,65 @@ "safe-buffer": "^5.0.1" } }, + "node_modules/lazystream": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/lazystream/-/lazystream-1.0.1.tgz", + "integrity": "sha512-b94GiNHQNy6JNTrt5w6zNyffMrNkXZb3KTkCZJb2V1xaEGCk093vkZ2jk3tpaeP33/OiXC+WvK9AxUebnf5nbw==", + "dependencies": { + "readable-stream": "^2.0.5" + }, + "engines": { + "node": ">= 0.6.3" + } + }, + "node_modules/leac": { + "version": "0.6.0", + "resolved": "https://registry.npmjs.org/leac/-/leac-0.6.0.tgz", + "integrity": "sha512-y+SqErxb8h7nE/fiEX07jsbuhrpO9lL8eca7/Y1nuWV2moNlXhyd59iDGcRf6moVyDMbmTNzL40SUyrFU/yDpg==", + "funding": { + "url": "https://ko-fi.com/killymxi" + } + }, + "node_modules/libbase64": { + "version": "1.3.0", + "resolved": "https://registry.npmjs.org/libbase64/-/libbase64-1.3.0.tgz", + "integrity": "sha512-GgOXd0Eo6phYgh0DJtjQ2tO8dc0IVINtZJeARPeiIJqge+HdsWSuaDTe8ztQ7j/cONByDZ3zeB325AHiv5O0dg==" + }, + "node_modules/libmime": { + "version": "5.3.7", + "resolved": "https://registry.npmjs.org/libmime/-/libmime-5.3.7.tgz", + "integrity": "sha512-FlDb3Wtha8P01kTL3P9M+ZDNDWPKPmKHWaU/cG/lg5pfuAwdflVpZE+wm9m7pKmC5ww6s+zTxBKS1p6yl3KpSw==", + "dependencies": { + "encoding-japanese": "2.2.0", + "iconv-lite": "0.6.3", + "libbase64": "1.3.0", + "libqp": "2.1.1" + } + }, + "node_modules/libmime/node_modules/iconv-lite": { + "version": "0.6.3", + "resolved": "https://registry.npmjs.org/iconv-lite/-/iconv-lite-0.6.3.tgz", + "integrity": "sha512-4fCk79wshMdzMp2rH06qWrJE4iolqLhCUH+OiuIgU++RB0+94NlDL81atO7GX55uUKueo0txHNtvEyI6D7WdMw==", + "dependencies": { + "safer-buffer": ">= 2.1.2 < 3.0.0" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/libqp": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/libqp/-/libqp-2.1.1.tgz", + "integrity": "sha512-0Wd+GPz1O134cP62YU2GTOPNA7Qgl09XwCqM5zpBv87ERCXdfDtyKXvV7c9U22yWJh44QZqBocFnXN11K96qow==" + }, + "node_modules/linkify-it": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/linkify-it/-/linkify-it-5.0.0.tgz", + "integrity": "sha512-5aHCbzQRADcdP+ATqnDuhhJ/MRIqDkZX5pyjFHRRysS8vZ5AbqGEoFIb6pYHPZ+L/OC2Lc+xT8uHVVR5CAK/wQ==", + "dependencies": { + "uc.micro": "^2.0.0" + } + }, "node_modules/lodash": { "version": "4.17.21", "resolved": "https://registry.npmjs.org/lodash/-/lodash-4.17.21.tgz", @@ -1299,6 +2106,43 @@ "resolved": "https://registry.npmjs.org/lodash.once/-/lodash.once-4.1.1.tgz", "integrity": "sha512-Sb487aTOCr9drQVL8pIxOzVhafOjZN9UU54hiN8PU3uAiSV7lx1yYNpbNmex2PK6dSJoNTSJUUswT651yww3Mg==" }, + "node_modules/lru-cache": { + "version": "10.4.3", + "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-10.4.3.tgz", + "integrity": "sha512-JNAzZcXrCt42VGLuYz0zfAzDfAvJWW6AfYlDBQyDV5DClI2m5sAmK+OIO7s59XfsRsWHp02jAJrRadPRGTt6SQ==" + }, + "node_modules/mailparser": { + "version": "3.9.3", + "resolved": "https://registry.npmjs.org/mailparser/-/mailparser-3.9.3.tgz", + "integrity": "sha512-AnB0a3zROum6fLaa52L+/K2SoRJVyFDk78Ea6q1D0ofcZLxWEWDtsS1+OrVqKbV7r5dulKL/AwYQccFGAPpuYQ==", + "dependencies": { + "@zone-eu/mailsplit": "5.4.8", + "encoding-japanese": "2.2.0", + "he": "1.2.0", + "html-to-text": "9.0.5", + "iconv-lite": "0.7.2", + "libmime": "5.3.7", + "linkify-it": "5.0.0", + "nodemailer": "7.0.13", + "punycode.js": "2.3.1", + "tlds": "1.261.0" + } + }, + "node_modules/mailparser/node_modules/iconv-lite": { + "version": "0.7.2", + "resolved": "https://registry.npmjs.org/iconv-lite/-/iconv-lite-0.7.2.tgz", + "integrity": "sha512-im9DjEDQ55s9fL4EYzOAv0yMqmMBSZp6G0VvFyTMPKWxiSBHUj9NW/qqLmXUwXrrM7AvqSlTCfvqRb0cM8yYqw==", + "dependencies": { + "safer-buffer": ">= 2.1.2 < 3.0.0" + }, + "engines": { + "node": ">=0.10.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/express" + } + }, "node_modules/math-intrinsics": { "version": "1.1.0", "resolved": "https://registry.npmjs.org/math-intrinsics/-/math-intrinsics-1.1.0.tgz", @@ -1361,6 +2205,20 @@ "node": ">= 0.6" } }, + "node_modules/minimatch": { + "version": "9.0.5", + "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-9.0.5.tgz", + "integrity": "sha512-G6T0ZX48xgozx7587koeX9Ys2NYy6Gmv//P89sEte9V9whIapMNF4idKxnW2QtCcLiTWlb/wfCabAtAFWhhBow==", + "dependencies": { + "brace-expansion": "^2.0.1" + }, + "engines": { + "node": ">=16 || 14 >=14.17" + }, + "funding": { + "url": "https://github.com/sponsors/isaacs" + } + }, "node_modules/minimist": { "version": "1.2.8", "resolved": "https://registry.npmjs.org/minimist/-/minimist-1.2.8.tgz", @@ -1369,6 +2227,14 @@ "url": "https://github.com/sponsors/ljharb" } }, + "node_modules/minipass": { + "version": "7.1.2", + "resolved": "https://registry.npmjs.org/minipass/-/minipass-7.1.2.tgz", + "integrity": "sha512-qOOzS1cBTWYF4BH8fVePDBOO9iptMnGUEZwNc/cMWnTV2nVLZ7VoNWEPHkYczZA0pdoA7dl6e7FL659nX9S2aw==", + "engines": { + "node": ">=16 || 14 >=14.17" + } + }, "node_modules/mkdirp": { "version": "0.5.6", "resolved": "https://registry.npmjs.org/mkdirp/-/mkdirp-0.5.6.tgz", @@ -1411,6 +2277,22 @@ "node": ">= 0.6" } }, + "node_modules/nodemailer": { + "version": "7.0.13", + "resolved": "https://registry.npmjs.org/nodemailer/-/nodemailer-7.0.13.tgz", + "integrity": "sha512-PNDFSJdP+KFgdsG3ZzMXCgquO7I6McjY2vlqILjtJd0hy8wEvtugS9xKRF2NWlPNGxvLCXlTNIae4serI7dinw==", + "engines": { + "node": ">=6.0.0" + } + }, + "node_modules/normalize-path": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/normalize-path/-/normalize-path-3.0.0.tgz", + "integrity": "sha512-6eZs5Ls3WtCisHWp9S2GUy8dqkpGi4BVSz3GaqiE6ezub0512ESztXUwUB6C6IKbQkY2Pnb/mD4WYojCRwcwLA==", + "engines": { + "node": ">=0.10.0" + } + }, "node_modules/object-assign": { "version": "4.1.1", "resolved": "https://registry.npmjs.org/object-assign/-/object-assign-4.1.1.tgz", @@ -1430,6 +2312,14 @@ "url": "https://github.com/sponsors/ljharb" } }, + "node_modules/on-exit-leak-free": { + "version": "2.1.2", + "resolved": "https://registry.npmjs.org/on-exit-leak-free/-/on-exit-leak-free-2.1.2.tgz", + "integrity": "sha512-0eJJY6hXLGf1udHwfNftBqH+g73EU4B504nZeKpz1sYRKafAghwxEJunB2O7rDZkL4PGfsMVnTXZ2EjibbqcsA==", + "engines": { + "node": ">=14.0.0" + } + }, "node_modules/on-finished": { "version": "2.4.1", "resolved": "https://registry.npmjs.org/on-finished/-/on-finished-2.4.1.tgz", @@ -1441,6 +2331,23 @@ "node": ">= 0.8" } }, + "node_modules/package-json-from-dist": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/package-json-from-dist/-/package-json-from-dist-1.0.1.tgz", + "integrity": "sha512-UEZIS3/by4OC8vL3P2dTXRETpebLI2NiI5vIrjaD/5UtrkFX/tNbwjTSRAGC/+7CAo2pIcBaRgWmcBBHcsaCIw==" + }, + "node_modules/parseley": { + "version": "0.12.1", + "resolved": "https://registry.npmjs.org/parseley/-/parseley-0.12.1.tgz", + "integrity": "sha512-e6qHKe3a9HWr0oMRVDTRhKce+bRO8VGQR3NyVwcjwrbhMmFCX9KszEV35+rn4AdilFAq9VPxP/Fe1wC9Qjd2lw==", + "dependencies": { + "leac": "^0.6.0", + "peberminta": "^0.9.0" + }, + "funding": { + "url": "https://ko-fi.com/killymxi" + } + }, "node_modules/parseurl": { "version": "1.3.3", "resolved": "https://registry.npmjs.org/parseurl/-/parseurl-1.3.3.tgz", @@ -1449,11 +2356,76 @@ "node": ">= 0.8" } }, + "node_modules/path-key": { + "version": "3.1.1", + "resolved": "https://registry.npmjs.org/path-key/-/path-key-3.1.1.tgz", + "integrity": "sha512-ojmeN0qd+y0jszEtoY48r0Peq5dwMEkIlCOu6Q5f41lfkswXuKtYrhgoTpLnyIcHm24Uhqx+5Tqm2InSwLhE6Q==", + "engines": { + "node": ">=8" + } + }, + "node_modules/path-scurry": { + "version": "1.11.1", + "resolved": "https://registry.npmjs.org/path-scurry/-/path-scurry-1.11.1.tgz", + "integrity": "sha512-Xa4Nw17FS9ApQFJ9umLiJS4orGjm7ZzwUrwamcGQuHSzDyth9boKDaycYdDcZDuqYATXw4HFXgaqWTctW/v1HA==", + "dependencies": { + "lru-cache": "^10.2.0", + "minipass": "^5.0.0 || ^6.0.2 || ^7.0.0" + }, + "engines": { + "node": ">=16 || 14 >=14.18" + }, + "funding": { + "url": "https://github.com/sponsors/isaacs" + } + }, "node_modules/path-to-regexp": { "version": "0.1.12", "resolved": "https://registry.npmjs.org/path-to-regexp/-/path-to-regexp-0.1.12.tgz", "integrity": "sha512-RA1GjUVMnvYFxuqovrEqZoxxW5NUZqbwKtYz/Tt7nXerk0LbLblQmrsgdeOxV5SFHf0UDggjS/bSeOZwt1pmEQ==" }, + "node_modules/peberminta": { + "version": "0.9.0", + "resolved": "https://registry.npmjs.org/peberminta/-/peberminta-0.9.0.tgz", + "integrity": "sha512-XIxfHpEuSJbITd1H3EeQwpcZbTLHc+VVr8ANI9t5sit565tsI4/xK3KWTUFE2e6QiangUkh3B0jihzmGnNrRsQ==", + "funding": { + "url": "https://ko-fi.com/killymxi" + } + }, + "node_modules/pino": { + "version": "10.3.0", + "resolved": "https://registry.npmjs.org/pino/-/pino-10.3.0.tgz", + "integrity": "sha512-0GNPNzHXBKw6U/InGe79A3Crzyk9bcSyObF9/Gfo9DLEf5qj5RF50RSjsu0W1rZ6ZqRGdzDFCRBQvi9/rSGPtA==", + "dependencies": { + "@pinojs/redact": "^0.4.0", + "atomic-sleep": "^1.0.0", + "on-exit-leak-free": "^2.1.0", + "pino-abstract-transport": "^3.0.0", + "pino-std-serializers": "^7.0.0", + "process-warning": "^5.0.0", + "quick-format-unescaped": "^4.0.3", + "real-require": "^0.2.0", + "safe-stable-stringify": "^2.3.1", + "sonic-boom": "^4.0.1", + "thread-stream": "^4.0.0" + }, + "bin": { + "pino": "bin.js" + } + }, + "node_modules/pino-abstract-transport": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/pino-abstract-transport/-/pino-abstract-transport-3.0.0.tgz", + "integrity": "sha512-wlfUczU+n7Hy/Ha5j9a/gZNy7We5+cXp8YL+X+PG8S0KXxw7n/JXA3c46Y0zQznIJ83URJiwy7Lh56WLokNuxg==", + "dependencies": { + "split2": "^4.0.0" + } + }, + "node_modules/pino-std-serializers": { + "version": "7.1.0", + "resolved": "https://registry.npmjs.org/pino-std-serializers/-/pino-std-serializers-7.1.0.tgz", + "integrity": "sha512-BndPH67/JxGExRgiX1dX0w1FvZck5Wa4aal9198SrRhZjH3GxKQUKIBnYJTdj2HDN3UQAS06HlfcSbQj2OHmaw==" + }, "node_modules/prisma": { "version": "5.22.0", "resolved": "https://registry.npmjs.org/prisma/-/prisma-5.22.0.tgz", @@ -1473,11 +2445,34 @@ "fsevents": "2.3.3" } }, + "node_modules/process": { + "version": "0.11.10", + "resolved": "https://registry.npmjs.org/process/-/process-0.11.10.tgz", + "integrity": "sha512-cdGef/drWFoydD1JsMzuFf8100nZl+GT+yacc2bEced5f9Rjk4z+WtFUTBu9PhOi9j/jfmBPu0mMEY4wIdAF8A==", + "engines": { + "node": ">= 0.6.0" + } + }, "node_modules/process-nextick-args": { "version": "2.0.1", "resolved": "https://registry.npmjs.org/process-nextick-args/-/process-nextick-args-2.0.1.tgz", "integrity": "sha512-3ouUOpQhtgrbOa17J7+uxOTpITYWaGP7/AhoR3+A+/1e9skrzelGi/dXzEYyvbxubEF6Wn2ypscTKiKJFFn1ag==" }, + "node_modules/process-warning": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/process-warning/-/process-warning-5.0.0.tgz", + "integrity": "sha512-a39t9ApHNx2L4+HBnQKqxxHNs1r7KF+Intd8Q/g1bUh6q0WIp9voPXJ/x0j+ZL45KF1pJd9+q2jLIRMfvEshkA==", + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/fastify" + }, + { + "type": "opencollective", + "url": "https://opencollective.com/fastify" + } + ] + }, "node_modules/proxy-addr": { "version": "2.0.7", "resolved": "https://registry.npmjs.org/proxy-addr/-/proxy-addr-2.0.7.tgz", @@ -1490,6 +2485,14 @@ "node": ">= 0.10" } }, + "node_modules/punycode.js": { + "version": "2.3.1", + "resolved": "https://registry.npmjs.org/punycode.js/-/punycode.js-2.3.1.tgz", + "integrity": "sha512-uxFIHU0YlHYhDQtV4R9J6a52SLx28BCjT+4ieh7IGbgwVJWO+km431c4yRlREUAsAmt/uMjQUyQHNEPf0M39CA==", + "engines": { + "node": ">=6" + } + }, "node_modules/qs": { "version": "6.14.1", "resolved": "https://registry.npmjs.org/qs/-/qs-6.14.1.tgz", @@ -1504,6 +2507,11 @@ "url": "https://github.com/sponsors/ljharb" } }, + "node_modules/quick-format-unescaped": { + "version": "4.0.4", + "resolved": "https://registry.npmjs.org/quick-format-unescaped/-/quick-format-unescaped-4.0.4.tgz", + "integrity": "sha512-tYC1Q1hgyRuHgloV/YXs2w15unPVh8qfu/qCTfhTYamaw7fyhumKa2yGpdSo87vY32rIclj+4fWYQXUMs9EHvg==" + }, "node_modules/range-parser": { "version": "1.2.1", "resolved": "https://registry.npmjs.org/range-parser/-/range-parser-1.2.1.tgz", @@ -1545,6 +2553,33 @@ "resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.1.2.tgz", "integrity": "sha512-Gd2UZBJDkXlY7GbJxfsE8/nvKkUEU1G38c1siN6QP6a9PT9MmHB8GnpscSmMJSoF8LOIrt8ud/wPtojys4G6+g==" }, + "node_modules/readdir-glob": { + "version": "1.1.3", + "resolved": "https://registry.npmjs.org/readdir-glob/-/readdir-glob-1.1.3.tgz", + "integrity": "sha512-v05I2k7xN8zXvPD9N+z/uhXPaj0sUFCe2rcWZIpBsqxfP7xXFQ0tipAd/wjj1YxWyWtUS5IDJpOG82JKt2EAVA==", + "dependencies": { + "minimatch": "^5.1.0" + } + }, + "node_modules/readdir-glob/node_modules/minimatch": { + "version": "5.1.6", + "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-5.1.6.tgz", + "integrity": "sha512-lKwV/1brpG6mBUFHtb7NUmtABCb2WZZmm2wNiOA5hAb8VdCS4B3dtMWyvcoViccwAW/COERjXLt0zP1zXUN26g==", + "dependencies": { + "brace-expansion": "^2.0.1" + }, + "engines": { + "node": ">=10" + } + }, + "node_modules/real-require": { + "version": "0.2.0", + "resolved": "https://registry.npmjs.org/real-require/-/real-require-0.2.0.tgz", + "integrity": "sha512-57frrGM/OCTLqLOAh0mhVA9VBMHd+9U7Zb2THMGdBUoZVOtGbJzjxsYGDJ3A9AYYCP4hn6y1TVbaOfzWtm5GFg==", + "engines": { + "node": ">= 12.13.0" + } + }, "node_modules/resolve-pkg-maps": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/resolve-pkg-maps/-/resolve-pkg-maps-1.0.0.tgz", @@ -1573,11 +2608,30 @@ } ] }, + "node_modules/safe-stable-stringify": { + "version": "2.5.0", + "resolved": "https://registry.npmjs.org/safe-stable-stringify/-/safe-stable-stringify-2.5.0.tgz", + "integrity": "sha512-b3rppTKm9T+PsVCBEOUR46GWI7fdOs00VKZ1+9c1EWDaDMvjQc6tUwuFyIprgGgTcWoVHSKrU8H31ZHA2e0RHA==", + "engines": { + "node": ">=10" + } + }, "node_modules/safer-buffer": { "version": "2.1.2", "resolved": "https://registry.npmjs.org/safer-buffer/-/safer-buffer-2.1.2.tgz", "integrity": "sha512-YZo3K82SD7Riyi0E1EQPojLz7kpepnSQI9IyPbHHg1XXXevb5dJI7tpyN2ADxGcQbHG7vcyRHk0cbwqcQriUtg==" }, + "node_modules/selderee": { + "version": "0.11.0", + "resolved": "https://registry.npmjs.org/selderee/-/selderee-0.11.0.tgz", + "integrity": "sha512-5TF+l7p4+OsnP8BCCvSyZiSPc4x4//p5uPwK8TCnVPJYRmU2aYKMpOXvw8zM5a5JvuuCGN1jmsMwuU2W02ukfA==", + "dependencies": { + "parseley": "^0.12.0" + }, + "funding": { + "url": "https://ko-fi.com/killymxi" + } + }, "node_modules/semver": { "version": "7.7.3", "resolved": "https://registry.npmjs.org/semver/-/semver-7.7.3.tgz", @@ -1636,6 +2690,25 @@ "resolved": "https://registry.npmjs.org/setprototypeof/-/setprototypeof-1.2.0.tgz", "integrity": "sha512-E5LDX7Wrp85Kil5bhZv46j8jOeboKq5JMmYM3gVGdGH8xFpPWXUMsNrlODCrkoxMEeNi/XZIwuRvY4XNwYMJpw==" }, + "node_modules/shebang-command": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/shebang-command/-/shebang-command-2.0.0.tgz", + "integrity": "sha512-kHxr2zZpYtdmrN1qDjrrX/Z1rR1kG8Dx+gkpK1G4eXmvXswmcE1hTWBWYUzlraYw1/yZp6YuDY77YtvbN0dmDA==", + "dependencies": { + "shebang-regex": "^3.0.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/shebang-regex": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/shebang-regex/-/shebang-regex-3.0.0.tgz", + "integrity": "sha512-7++dFhtcx3353uBaq8DDR4NuxBetBzC7ZQOhmTQInHEd6bSrXdiEyzCvG07Z44UYdLShWUyXt5M/yhz8ekcb1A==", + "engines": { + "node": ">=8" + } + }, "node_modules/side-channel": { "version": "1.1.0", "resolved": "https://registry.npmjs.org/side-channel/-/side-channel-1.1.0.tgz", @@ -1704,6 +2777,55 @@ "url": "https://github.com/sponsors/ljharb" } }, + "node_modules/signal-exit": { + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/signal-exit/-/signal-exit-4.1.0.tgz", + "integrity": "sha512-bzyZ1e88w9O1iNJbKnOlvYTrWPDl46O1bG0D3XInv+9tkPrxrN8jUUTiFlDkkmKWgn1M6CfIA13SuGqOa9Korw==", + "engines": { + "node": ">=14" + }, + "funding": { + "url": "https://github.com/sponsors/isaacs" + } + }, + "node_modules/smart-buffer": { + "version": "4.2.0", + "resolved": "https://registry.npmjs.org/smart-buffer/-/smart-buffer-4.2.0.tgz", + "integrity": "sha512-94hK0Hh8rPqQl2xXc3HsaBoOXKV20MToPkcXvwbISWLEs+64sBq5kFgn2kJDHb1Pry9yrP0dxrCI9RRci7RXKg==", + "engines": { + "node": ">= 6.0.0", + "npm": ">= 3.0.0" + } + }, + "node_modules/socks": { + "version": "2.8.7", + "resolved": "https://registry.npmjs.org/socks/-/socks-2.8.7.tgz", + "integrity": "sha512-HLpt+uLy/pxB+bum/9DzAgiKS8CX1EvbWxI4zlmgGCExImLdiad2iCwXT5Z4c9c3Eq8rP2318mPW2c+QbtjK8A==", + "dependencies": { + "ip-address": "^10.0.1", + "smart-buffer": "^4.2.0" + }, + "engines": { + "node": ">= 10.0.0", + "npm": ">= 3.0.0" + } + }, + "node_modules/sonic-boom": { + "version": "4.2.0", + "resolved": "https://registry.npmjs.org/sonic-boom/-/sonic-boom-4.2.0.tgz", + "integrity": "sha512-INb7TM37/mAcsGmc9hyyI6+QR3rR1zVRu36B0NeGXKnOOLiZOfER5SA+N7X7k3yUYRzLWafduTDvJAfDswwEww==", + "dependencies": { + "atomic-sleep": "^1.0.0" + } + }, + "node_modules/split2": { + "version": "4.2.0", + "resolved": "https://registry.npmjs.org/split2/-/split2-4.2.0.tgz", + "integrity": "sha512-UcjcJOWknrNkF6PLX83qcHM6KHgVKNkV62Y8a5uYDVv9ydGQVwAHMKqHdJje1VTWpljG0WYpCDhrCdAOYH4TWg==", + "engines": { + "node": ">= 10.x" + } + }, "node_modules/statuses": { "version": "2.0.2", "resolved": "https://registry.npmjs.org/statuses/-/statuses-2.0.2.tgz", @@ -1720,6 +2842,16 @@ "node": ">=10.0.0" } }, + "node_modules/streamx": { + "version": "2.23.0", + "resolved": "https://registry.npmjs.org/streamx/-/streamx-2.23.0.tgz", + "integrity": "sha512-kn+e44esVfn2Fa/O0CPFcex27fjIL6MkVae0Mm6q+E6f0hWv578YCERbv+4m02cjxvDsPKLnmxral/rR6lBMAg==", + "dependencies": { + "events-universal": "^1.0.0", + "fast-fifo": "^1.3.2", + "text-decoder": "^1.1.0" + } + }, "node_modules/string_decoder": { "version": "1.1.1", "resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-1.1.1.tgz", @@ -1733,6 +2865,131 @@ "resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.1.2.tgz", "integrity": "sha512-Gd2UZBJDkXlY7GbJxfsE8/nvKkUEU1G38c1siN6QP6a9PT9MmHB8GnpscSmMJSoF8LOIrt8ud/wPtojys4G6+g==" }, + "node_modules/string-width": { + "version": "5.1.2", + "resolved": "https://registry.npmjs.org/string-width/-/string-width-5.1.2.tgz", + "integrity": "sha512-HnLOCR3vjcY8beoNLtcjZ5/nxn2afmME6lhrDrebokqMap+XbeW8n9TXpPDOqdGK5qcI3oT0GKTW6wC7EMiVqA==", + "dependencies": { + "eastasianwidth": "^0.2.0", + "emoji-regex": "^9.2.2", + "strip-ansi": "^7.0.1" + }, + "engines": { + "node": ">=12" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/string-width-cjs": { + "name": "string-width", + "version": "4.2.3", + "resolved": "https://registry.npmjs.org/string-width/-/string-width-4.2.3.tgz", + "integrity": "sha512-wKyQRQpjJ0sIp62ErSZdGsjMJWsap5oRNihHhu6G7JVO/9jIB6UyevL+tXuOqrng8j/cxKTWyWUwvSTriiZz/g==", + "dependencies": { + "emoji-regex": "^8.0.0", + "is-fullwidth-code-point": "^3.0.0", + "strip-ansi": "^6.0.1" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/string-width-cjs/node_modules/ansi-regex": { + "version": "5.0.1", + "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-5.0.1.tgz", + "integrity": "sha512-quJQXlTSUGL2LH9SUXo8VwsY4soanhgo6LNSm84E1LBcE8s3O0wpdiRzyR9z/ZZJMlMWv37qOOb9pdJlMUEKFQ==", + "engines": { + "node": ">=8" + } + }, + "node_modules/string-width-cjs/node_modules/emoji-regex": { + "version": "8.0.0", + "resolved": "https://registry.npmjs.org/emoji-regex/-/emoji-regex-8.0.0.tgz", + "integrity": "sha512-MSjYzcWNOA0ewAHpz0MxpYFvwg6yjy1NG3xteoqz644VCo/RPgnr1/GGt+ic3iJTzQ8Eu3TdM14SawnVUmGE6A==" + }, + "node_modules/string-width-cjs/node_modules/strip-ansi": { + "version": "6.0.1", + "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-6.0.1.tgz", + "integrity": "sha512-Y38VPSHcqkFrCpFnQ9vuSXmquuv5oXOKpGeT6aGrr3o3Gc9AlVa6JBfUSOCnbxGGZF+/0ooI7KrPuUSztUdU5A==", + "dependencies": { + "ansi-regex": "^5.0.1" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/strip-ansi": { + "version": "7.1.2", + "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-7.1.2.tgz", + "integrity": "sha512-gmBGslpoQJtgnMAvOVqGZpEz9dyoKTCzy2nfz/n8aIFhN/jCE/rCmcxabB6jOOHV+0WNnylOxaxBQPSvcWklhA==", + "dependencies": { + "ansi-regex": "^6.0.1" + }, + "engines": { + "node": ">=12" + }, + "funding": { + "url": "https://github.com/chalk/strip-ansi?sponsor=1" + } + }, + "node_modules/strip-ansi-cjs": { + "name": "strip-ansi", + "version": "6.0.1", + "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-6.0.1.tgz", + "integrity": "sha512-Y38VPSHcqkFrCpFnQ9vuSXmquuv5oXOKpGeT6aGrr3o3Gc9AlVa6JBfUSOCnbxGGZF+/0ooI7KrPuUSztUdU5A==", + "dependencies": { + "ansi-regex": "^5.0.1" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/strip-ansi-cjs/node_modules/ansi-regex": { + "version": "5.0.1", + "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-5.0.1.tgz", + "integrity": "sha512-quJQXlTSUGL2LH9SUXo8VwsY4soanhgo6LNSm84E1LBcE8s3O0wpdiRzyR9z/ZZJMlMWv37qOOb9pdJlMUEKFQ==", + "engines": { + "node": ">=8" + } + }, + "node_modules/tar-stream": { + "version": "3.1.7", + "resolved": "https://registry.npmjs.org/tar-stream/-/tar-stream-3.1.7.tgz", + "integrity": "sha512-qJj60CXt7IU1Ffyc3NJMjh6EkuCFej46zUqJ4J7pqYlThyd9bO0XBTmcOIhSzZJVWfsLks0+nle/j538YAW9RQ==", + "dependencies": { + "b4a": "^1.6.4", + "fast-fifo": "^1.2.0", + "streamx": "^2.15.0" + } + }, + "node_modules/text-decoder": { + "version": "1.2.3", + "resolved": "https://registry.npmjs.org/text-decoder/-/text-decoder-1.2.3.tgz", + "integrity": "sha512-3/o9z3X0X0fTupwsYvR03pJ/DjWuqqrfwBgTQzdWDiQSm9KitAyz/9WqsT2JQW7KV2m+bC2ol/zqpW37NHxLaA==", + "dependencies": { + "b4a": "^1.6.4" + } + }, + "node_modules/thread-stream": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/thread-stream/-/thread-stream-4.0.0.tgz", + "integrity": "sha512-4iMVL6HAINXWf1ZKZjIPcz5wYaOdPhtO8ATvZ+Xqp3BTdaqtAwQkNmKORqcIo5YkQqGXq5cwfswDwMqqQNrpJA==", + "dependencies": { + "real-require": "^0.2.0" + }, + "engines": { + "node": ">=20" + } + }, + "node_modules/tlds": { + "version": "1.261.0", + "resolved": "https://registry.npmjs.org/tlds/-/tlds-1.261.0.tgz", + "integrity": "sha512-QXqwfEl9ddlGBaRFXIvNKK6OhipSiLXuRuLJX5DErz0o0Q0rYxulWLdFryTkV5PkdZct5iMInwYEGe/eR++1AA==", + "bin": { + "tlds": "bin.js" + } + }, "node_modules/toidentifier": { "version": "1.0.1", "resolved": "https://registry.npmjs.org/toidentifier/-/toidentifier-1.0.1.tgz", @@ -1790,6 +3047,11 @@ "node": ">=14.17" } }, + "node_modules/uc.micro": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/uc.micro/-/uc.micro-2.1.0.tgz", + "integrity": "sha512-ARDJmphmdvUk6Glw7y9DQ2bFkKBHwQHLi2lsaH6PPmz/Ka9sFOBsBluozhDltWmnv9u/cF6Rt87znRTPV+yp/A==" + }, "node_modules/undici": { "version": "6.23.0", "resolved": "https://registry.npmjs.org/undici/-/undici-6.23.0.tgz", @@ -1841,6 +3103,104 @@ "node": ">= 0.8" } }, + "node_modules/which": { + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/which/-/which-2.0.2.tgz", + "integrity": "sha512-BLI3Tl1TW3Pvl70l3yq3Y64i+awpwXqsGBYWkkqMtnbXgrMD+yj7rhW0kuEDxzJaYXGjEW5ogapKNMEKNMjibA==", + "dependencies": { + "isexe": "^2.0.0" + }, + "bin": { + "node-which": "bin/node-which" + }, + "engines": { + "node": ">= 8" + } + }, + "node_modules/wrap-ansi": { + "version": "8.1.0", + "resolved": "https://registry.npmjs.org/wrap-ansi/-/wrap-ansi-8.1.0.tgz", + "integrity": "sha512-si7QWI6zUMq56bESFvagtmzMdGOtoxfR+Sez11Mobfc7tm+VkUckk9bW2UeffTGVUbOksxmSw0AA2gs8g71NCQ==", + "dependencies": { + "ansi-styles": "^6.1.0", + "string-width": "^5.0.1", + "strip-ansi": "^7.0.1" + }, + "engines": { + "node": ">=12" + }, + "funding": { + "url": "https://github.com/chalk/wrap-ansi?sponsor=1" + } + }, + "node_modules/wrap-ansi-cjs": { + "name": "wrap-ansi", + "version": "7.0.0", + "resolved": "https://registry.npmjs.org/wrap-ansi/-/wrap-ansi-7.0.0.tgz", + "integrity": "sha512-YVGIj2kamLSTxw6NsZjoBxfSwsn0ycdesmc4p+Q21c5zPuZ1pl+NfxVdxPtdHvmNVOQ6XSYG4AUtyt/Fi7D16Q==", + "dependencies": { + "ansi-styles": "^4.0.0", + "string-width": "^4.1.0", + "strip-ansi": "^6.0.0" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/chalk/wrap-ansi?sponsor=1" + } + }, + "node_modules/wrap-ansi-cjs/node_modules/ansi-regex": { + "version": "5.0.1", + "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-5.0.1.tgz", + "integrity": "sha512-quJQXlTSUGL2LH9SUXo8VwsY4soanhgo6LNSm84E1LBcE8s3O0wpdiRzyR9z/ZZJMlMWv37qOOb9pdJlMUEKFQ==", + "engines": { + "node": ">=8" + } + }, + "node_modules/wrap-ansi-cjs/node_modules/ansi-styles": { + "version": "4.3.0", + "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.3.0.tgz", + "integrity": "sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==", + "dependencies": { + "color-convert": "^2.0.1" + }, + "engines": { + "node": ">=8" + }, + "funding": { + "url": "https://github.com/chalk/ansi-styles?sponsor=1" + } + }, + "node_modules/wrap-ansi-cjs/node_modules/emoji-regex": { + "version": "8.0.0", + "resolved": "https://registry.npmjs.org/emoji-regex/-/emoji-regex-8.0.0.tgz", + "integrity": "sha512-MSjYzcWNOA0ewAHpz0MxpYFvwg6yjy1NG3xteoqz644VCo/RPgnr1/GGt+ic3iJTzQ8Eu3TdM14SawnVUmGE6A==" + }, + "node_modules/wrap-ansi-cjs/node_modules/string-width": { + "version": "4.2.3", + "resolved": "https://registry.npmjs.org/string-width/-/string-width-4.2.3.tgz", + "integrity": "sha512-wKyQRQpjJ0sIp62ErSZdGsjMJWsap5oRNihHhu6G7JVO/9jIB6UyevL+tXuOqrng8j/cxKTWyWUwvSTriiZz/g==", + "dependencies": { + "emoji-regex": "^8.0.0", + "is-fullwidth-code-point": "^3.0.0", + "strip-ansi": "^6.0.1" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/wrap-ansi-cjs/node_modules/strip-ansi": { + "version": "6.0.1", + "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-6.0.1.tgz", + "integrity": "sha512-Y38VPSHcqkFrCpFnQ9vuSXmquuv5oXOKpGeT6aGrr3o3Gc9AlVa6JBfUSOCnbxGGZF+/0ooI7KrPuUSztUdU5A==", + "dependencies": { + "ansi-regex": "^5.0.1" + }, + "engines": { + "node": ">=8" + } + }, "node_modules/xtend": { "version": "4.0.2", "resolved": "https://registry.npmjs.org/xtend/-/xtend-4.0.2.tgz", @@ -1848,6 +3208,42 @@ "engines": { "node": ">=0.4" } + }, + "node_modules/zip-stream": { + "version": "6.0.1", + "resolved": "https://registry.npmjs.org/zip-stream/-/zip-stream-6.0.1.tgz", + "integrity": "sha512-zK7YHHz4ZXpW89AHXUPbQVGKI7uvkd3hzusTdotCg1UxyaVtg0zFJSTfW/Dq5f7OBBVnq6cZIaC8Ti4hb6dtCA==", + "dependencies": { + "archiver-utils": "^5.0.0", + "compress-commons": "^6.0.2", + "readable-stream": "^4.0.0" + }, + "engines": { + "node": ">= 14" + } + }, + "node_modules/zip-stream/node_modules/readable-stream": { + "version": "4.7.0", + "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-4.7.0.tgz", + "integrity": "sha512-oIGGmcpTLwPga8Bn6/Z75SVaH1z5dUut2ibSyAMVhmUggWpmDn2dapB0n7f8nwaSiRtepAsfJyfXIO5DCVAODg==", + "dependencies": { + "abort-controller": "^3.0.0", + "buffer": "^6.0.3", + "events": "^3.3.0", + "process": "^0.11.10", + "string_decoder": "^1.3.0" + }, + "engines": { + "node": "^12.22.0 || ^14.17.0 || >=16.0.0" + } + }, + "node_modules/zip-stream/node_modules/string_decoder": { + "version": "1.3.0", + "resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-1.3.0.tgz", + "integrity": "sha512-hkRX8U1WjJFd8LsDJ2yQ/wWWxaopEsABU1XfkM8A+j0+85JAGppt16cr1Whg6KIbb4okU6Mql6BOj+uup/wKeA==", + "dependencies": { + "safe-buffer": "~5.2.0" + } } } } diff --git a/backend/package.json b/backend/package.json index 230e1a73..db7ba247 100644 --- a/backend/package.json +++ b/backend/package.json @@ -13,26 +13,37 @@ "db:migrate": "prisma migrate dev", "db:push": "prisma db push", "db:seed": "tsx prisma/seed.ts", - "db:studio": "prisma studio" + "db:studio": "prisma studio", + "db:backup": "tsx prisma/backup-data.ts", + "db:restore": "tsx prisma/restore-data.ts" }, "dependencies": { "@prisma/client": "^5.22.0", + "adm-zip": "^0.5.16", + "archiver": "^7.0.1", "bcryptjs": "^2.4.3", "cors": "^2.8.5", "dotenv": "^16.4.5", "express": "^4.21.1", "express-validator": "^7.2.0", + "imapflow": "^1.2.8", "jsonwebtoken": "^9.0.2", + "mailparser": "^3.9.3", "multer": "^1.4.5-lts.1", + "nodemailer": "^7.0.13", "undici": "^6.23.0" }, "devDependencies": { + "@types/adm-zip": "^0.5.7", + "@types/archiver": "^7.0.0", "@types/bcryptjs": "^2.4.6", "@types/cors": "^2.8.17", "@types/express": "^4.17.25", "@types/jsonwebtoken": "^9.0.7", + "@types/mailparser": "^3.4.6", "@types/multer": "^1.4.12", "@types/node": "^22.9.0", + "@types/nodemailer": "^7.0.9", "prisma": "^5.22.0", "tsx": "^4.19.2", "typescript": "^5.6.3" diff --git a/backend/prisma/add-email-delete-permission.ts b/backend/prisma/add-email-delete-permission.ts new file mode 100644 index 00000000..5ea56b7c --- /dev/null +++ b/backend/prisma/add-email-delete-permission.ts @@ -0,0 +1,88 @@ +import { PrismaClient } from '@prisma/client'; + +const prisma = new PrismaClient(); + +async function main() { + console.log('Adding/updating permissions and Developer role...'); + + // 1. Create or get the emails:delete permission + const emailsDeletePerm = await prisma.permission.upsert({ + where: { resource_action: { resource: 'emails', action: 'delete' } }, + update: {}, + create: { resource: 'emails', action: 'delete' }, + }); + console.log('emails:delete permission created/found'); + + // 2. Create or get the developer:access permission + const developerAccessPerm = await prisma.permission.upsert({ + where: { resource_action: { resource: 'developer', action: 'access' } }, + update: {}, + create: { resource: 'developer', action: 'access' }, + }); + console.log('developer:access permission created/found'); + + // 3. Create Developer role if it doesn't exist + let developerRole = await prisma.role.findUnique({ + where: { name: 'Developer' }, + }); + + if (!developerRole) { + // Get all permissions for Developer role + const allPermissions = await prisma.permission.findMany(); + developerRole = await prisma.role.create({ + data: { + name: 'Developer', + description: 'Voller Zugriff inkl. Entwickler-Tools', + permissions: { + create: allPermissions.map(p => ({ permissionId: p.id })), + }, + }, + }); + console.log('Developer role created with all permissions'); + } + + // 4. Add emails:delete to Admin and Developer + const rolesToUpdate = [ + { name: 'Admin', permissions: [emailsDeletePerm] }, + { name: 'Developer', permissions: [emailsDeletePerm, developerAccessPerm] }, + ]; + + for (const roleConfig of rolesToUpdate) { + const role = await prisma.role.findUnique({ + where: { name: roleConfig.name }, + include: { permissions: true }, + }); + + if (!role) { + console.log(`${roleConfig.name} role not found, skipping...`); + continue; + } + + for (const perm of roleConfig.permissions) { + const hasPermission = role.permissions.some( + (rp) => rp.permissionId === perm.id + ); + + if (!hasPermission) { + await prisma.rolePermission.create({ + data: { + roleId: role.id, + permissionId: perm.id, + }, + }); + console.log(`Added ${perm.resource}:${perm.action} to ${roleConfig.name}`); + } + } + } + + console.log('Done!'); +} + +main() + .catch((e) => { + console.error(e); + process.exit(1); + }) + .finally(async () => { + await prisma.$disconnect(); + }); diff --git a/backend/prisma/backup-data.ts b/backend/prisma/backup-data.ts new file mode 100644 index 00000000..2ae2dcba --- /dev/null +++ b/backend/prisma/backup-data.ts @@ -0,0 +1,114 @@ +/** + * Datenbank-Backup Script + * + * Exportiert alle Daten als JSON-Dateien für die Wiederherstellung nach Migrationen. + * + * Verwendung: + * npx ts-node prisma/backup-data.ts + * + * Erstellt einen Ordner 'backups/YYYY-MM-DD_HH-mm-ss/' mit JSON-Dateien pro Tabelle. + */ + +import { PrismaClient } from '@prisma/client'; +import * as fs from 'fs'; +import * as path from 'path'; + +const prisma = new PrismaClient(); + +async function main() { + // Backup-Ordner mit Zeitstempel erstellen + const timestamp = new Date().toISOString().replace(/[:.]/g, '-').slice(0, 19); + const backupDir = path.join(__dirname, 'backups', timestamp); + + if (!fs.existsSync(backupDir)) { + fs.mkdirSync(backupDir, { recursive: true }); + } + + console.log(`\n📦 Starte Datenbank-Backup nach: ${backupDir}\n`); + + // Tabellen in Abhängigkeitsreihenfolge (unabhängige zuerst) + const tables = [ + // Level 0: Keine Abhängigkeiten + { name: 'Permission', query: () => prisma.permission.findMany() }, + { name: 'Role', query: () => prisma.role.findMany() }, + { name: 'SalesPlatform', query: () => prisma.salesPlatform.findMany() }, + { name: 'ContractCategory', query: () => prisma.contractCategory.findMany() }, + { name: 'CancellationPeriod', query: () => prisma.cancellationPeriod.findMany() }, + { name: 'ContractDuration', query: () => prisma.contractDuration.findMany() }, + { name: 'AppSetting', query: () => prisma.appSetting.findMany() }, + { name: 'EmailProviderConfig', query: () => prisma.emailProviderConfig.findMany() }, + { name: 'EnergyProvider', query: () => prisma.energyProvider.findMany() }, + { name: 'TelecomProvider', query: () => prisma.telecomProvider.findMany() }, + + // Level 1: Abhängig von Level 0 + { name: 'RolePermission', query: () => prisma.rolePermission.findMany() }, + { name: 'User', query: () => prisma.user.findMany() }, + { name: 'Customer', query: () => prisma.customer.findMany() }, + { name: 'Tariff', query: () => prisma.tariff.findMany() }, + + // Level 2: Abhängig von Level 1 + { name: 'UserRole', query: () => prisma.userRole.findMany() }, + { name: 'CustomerRepresentative', query: () => prisma.customerRepresentative.findMany() }, + { name: 'StressfreiEmail', query: () => prisma.stressfreiEmail.findMany() }, + { name: 'Contract', query: () => prisma.contract.findMany() }, + { name: 'Meter', query: () => prisma.meter.findMany() }, + + // Level 3: Abhängig von Level 2 + { name: 'CachedEmail', query: () => prisma.cachedEmail.findMany() }, + { name: 'ContractTask', query: () => prisma.contractTask.findMany() }, + { name: 'MeterReading', query: () => prisma.meterReading.findMany() }, + { name: 'ContractNote', query: () => prisma.contractNote.findMany() }, + { name: 'ContractDocument', query: () => prisma.contractDocument.findMany() }, + + // Level 4: Abhängig von Level 3 + { name: 'ContractTaskSubtask', query: () => prisma.contractTaskSubtask.findMany() }, + + // Vertragstyp-spezifische Details + { name: 'EnergyContractDetails', query: () => prisma.energyContractDetails.findMany() }, + { name: 'TelecomContractDetails', query: () => prisma.telecomContractDetails.findMany() }, + { name: 'CarInsuranceDetails', query: () => prisma.carInsuranceDetails.findMany() }, + ]; + + let totalRecords = 0; + const stats: { table: string; count: number }[] = []; + + for (const table of tables) { + try { + const data = await table.query(); + const count = data.length; + totalRecords += count; + stats.push({ table: table.name, count }); + + // JSON-Datei schreiben + const filePath = path.join(backupDir, `${table.name}.json`); + fs.writeFileSync(filePath, JSON.stringify(data, null, 2)); + + const status = count > 0 ? '✅' : '⚪'; + console.log(`${status} ${table.name}: ${count} Einträge`); + } catch (error: any) { + // Tabelle existiert möglicherweise nicht (bei älteren Schema-Versionen) + console.log(`⚠️ ${table.name}: Übersprungen (${error.message?.slice(0, 50)}...)`); + } + } + + // Backup-Info speichern + const backupInfo = { + timestamp: new Date().toISOString(), + totalRecords, + tables: stats, + }; + fs.writeFileSync(path.join(backupDir, '_backup-info.json'), JSON.stringify(backupInfo, null, 2)); + + console.log(`\n✅ Backup abgeschlossen!`); + console.log(` 📊 ${totalRecords} Datensätze in ${stats.filter(s => s.count > 0).length} Tabellen`); + console.log(` 📁 Gespeichert in: ${backupDir}\n`); +} + +main() + .catch((e) => { + console.error('❌ Backup fehlgeschlagen:', e); + process.exit(1); + }) + .finally(async () => { + await prisma.$disconnect(); + }); diff --git a/backend/prisma/backups/.gitkeep b/backend/prisma/backups/.gitkeep new file mode 100644 index 00000000..e69de29b diff --git a/backend/prisma/migrations/20260130231219_add_email_trash_fields/migration.sql b/backend/prisma/migrations/20260130231219_add_email_trash_fields/migration.sql new file mode 100644 index 00000000..0ee61b34 --- /dev/null +++ b/backend/prisma/migrations/20260130231219_add_email_trash_fields/migration.sql @@ -0,0 +1,180 @@ +/* + Warnings: + + - A unique constraint covering the columns `[portalEmail]` on the table `Customer` will be added. If there are existing duplicate values, this will fail. + +*/ +-- AlterTable +ALTER TABLE `Contract` ADD COLUMN `stressfreiEmailId` INTEGER NULL, + MODIFY `status` ENUM('DRAFT', 'PENDING', 'ACTIVE', 'CANCELLED', 'EXPIRED', 'DEACTIVATED') NOT NULL DEFAULT 'DRAFT'; + +-- AlterTable +ALTER TABLE `Customer` ADD COLUMN `portalEmail` VARCHAR(191) NULL, + ADD COLUMN `portalEnabled` BOOLEAN NOT NULL DEFAULT false, + ADD COLUMN `portalLastLogin` DATETIME(3) NULL, + ADD COLUMN `portalPasswordEncrypted` VARCHAR(191) NULL, + ADD COLUMN `portalPasswordHash` VARCHAR(191) NULL; + +-- CreateTable +CREATE TABLE `AppSetting` ( + `id` INTEGER NOT NULL AUTO_INCREMENT, + `key` VARCHAR(191) NOT NULL, + `value` TEXT NOT NULL, + `createdAt` DATETIME(3) NOT NULL DEFAULT CURRENT_TIMESTAMP(3), + `updatedAt` DATETIME(3) NOT NULL, + + UNIQUE INDEX `AppSetting_key_key`(`key`), + PRIMARY KEY (`id`) +) DEFAULT CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci; + +-- CreateTable +CREATE TABLE `CustomerRepresentative` ( + `id` INTEGER NOT NULL AUTO_INCREMENT, + `customerId` INTEGER NOT NULL, + `representativeId` INTEGER NOT NULL, + `notes` VARCHAR(191) NULL, + `isActive` BOOLEAN NOT NULL DEFAULT true, + `createdAt` DATETIME(3) NOT NULL DEFAULT CURRENT_TIMESTAMP(3), + `updatedAt` DATETIME(3) NOT NULL, + + UNIQUE INDEX `CustomerRepresentative_customerId_representativeId_key`(`customerId`, `representativeId`), + PRIMARY KEY (`id`) +) DEFAULT CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci; + +-- CreateTable +CREATE TABLE `EmailProviderConfig` ( + `id` INTEGER NOT NULL AUTO_INCREMENT, + `name` VARCHAR(191) NOT NULL, + `type` ENUM('PLESK', 'CPANEL', 'DIRECTADMIN') NOT NULL, + `apiUrl` VARCHAR(191) NOT NULL, + `apiKey` VARCHAR(191) NULL, + `username` VARCHAR(191) NULL, + `passwordEncrypted` VARCHAR(191) NULL, + `domain` VARCHAR(191) NOT NULL, + `defaultForwardEmail` VARCHAR(191) NULL, + `imapServer` VARCHAR(191) NULL, + `imapPort` INTEGER NULL DEFAULT 993, + `smtpServer` VARCHAR(191) NULL, + `smtpPort` INTEGER NULL DEFAULT 465, + `imapEncryption` ENUM('SSL', 'STARTTLS', 'NONE') NOT NULL DEFAULT 'SSL', + `smtpEncryption` ENUM('SSL', 'STARTTLS', 'NONE') NOT NULL DEFAULT 'SSL', + `allowSelfSignedCerts` BOOLEAN NOT NULL DEFAULT false, + `isActive` BOOLEAN NOT NULL DEFAULT true, + `isDefault` BOOLEAN NOT NULL DEFAULT false, + `createdAt` DATETIME(3) NOT NULL DEFAULT CURRENT_TIMESTAMP(3), + `updatedAt` DATETIME(3) NOT NULL, + + UNIQUE INDEX `EmailProviderConfig_name_key`(`name`), + PRIMARY KEY (`id`) +) DEFAULT CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci; + +-- CreateTable +CREATE TABLE `StressfreiEmail` ( + `id` INTEGER NOT NULL AUTO_INCREMENT, + `customerId` INTEGER NOT NULL, + `email` VARCHAR(191) NOT NULL, + `platform` VARCHAR(191) NULL, + `notes` TEXT NULL, + `isActive` BOOLEAN NOT NULL DEFAULT true, + `isProvisioned` BOOLEAN NOT NULL DEFAULT false, + `provisionedAt` DATETIME(3) NULL, + `provisionError` TEXT NULL, + `hasMailbox` BOOLEAN NOT NULL DEFAULT false, + `emailPasswordEncrypted` VARCHAR(191) NULL, + `createdAt` DATETIME(3) NOT NULL DEFAULT CURRENT_TIMESTAMP(3), + `updatedAt` DATETIME(3) NOT NULL, + + PRIMARY KEY (`id`) +) DEFAULT CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci; + +-- CreateTable +CREATE TABLE `CachedEmail` ( + `id` INTEGER NOT NULL AUTO_INCREMENT, + `stressfreiEmailId` INTEGER NOT NULL, + `folder` ENUM('INBOX', 'SENT') NOT NULL DEFAULT 'INBOX', + `messageId` VARCHAR(191) NOT NULL, + `uid` INTEGER NOT NULL, + `subject` VARCHAR(191) NULL, + `fromAddress` VARCHAR(191) NOT NULL, + `fromName` VARCHAR(191) NULL, + `toAddresses` TEXT NOT NULL, + `ccAddresses` TEXT NULL, + `receivedAt` DATETIME(3) NOT NULL, + `textBody` LONGTEXT NULL, + `htmlBody` LONGTEXT NULL, + `hasAttachments` BOOLEAN NOT NULL DEFAULT false, + `attachmentNames` TEXT NULL, + `contractId` INTEGER NULL, + `assignedAt` DATETIME(3) NULL, + `assignedBy` INTEGER NULL, + `isAutoAssigned` BOOLEAN NOT NULL DEFAULT false, + `isRead` BOOLEAN NOT NULL DEFAULT false, + `isStarred` BOOLEAN NOT NULL DEFAULT false, + `isDeleted` BOOLEAN NOT NULL DEFAULT false, + `deletedAt` DATETIME(3) NULL, + `createdAt` DATETIME(3) NOT NULL DEFAULT CURRENT_TIMESTAMP(3), + `updatedAt` DATETIME(3) NOT NULL, + + INDEX `CachedEmail_contractId_idx`(`contractId`), + INDEX `CachedEmail_stressfreiEmailId_folder_receivedAt_idx`(`stressfreiEmailId`, `folder`, `receivedAt`), + INDEX `CachedEmail_stressfreiEmailId_isDeleted_idx`(`stressfreiEmailId`, `isDeleted`), + UNIQUE INDEX `CachedEmail_stressfreiEmailId_messageId_folder_key`(`stressfreiEmailId`, `messageId`, `folder`), + PRIMARY KEY (`id`) +) DEFAULT CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci; + +-- CreateTable +CREATE TABLE `ContractTask` ( + `id` INTEGER NOT NULL AUTO_INCREMENT, + `contractId` INTEGER NOT NULL, + `title` VARCHAR(191) NOT NULL, + `description` TEXT NULL, + `status` ENUM('OPEN', 'COMPLETED') NOT NULL DEFAULT 'OPEN', + `visibleInPortal` BOOLEAN NOT NULL DEFAULT false, + `createdBy` VARCHAR(191) NULL, + `completedAt` DATETIME(3) NULL, + `createdAt` DATETIME(3) NOT NULL DEFAULT CURRENT_TIMESTAMP(3), + `updatedAt` DATETIME(3) NOT NULL, + + PRIMARY KEY (`id`) +) DEFAULT CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci; + +-- CreateTable +CREATE TABLE `ContractTaskSubtask` ( + `id` INTEGER NOT NULL AUTO_INCREMENT, + `taskId` INTEGER NOT NULL, + `title` VARCHAR(191) NOT NULL, + `status` ENUM('OPEN', 'COMPLETED') NOT NULL DEFAULT 'OPEN', + `createdBy` VARCHAR(191) NULL, + `completedAt` DATETIME(3) NULL, + `createdAt` DATETIME(3) NOT NULL DEFAULT CURRENT_TIMESTAMP(3), + `updatedAt` DATETIME(3) NOT NULL, + + PRIMARY KEY (`id`) +) DEFAULT CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci; + +-- CreateIndex +CREATE UNIQUE INDEX `Customer_portalEmail_key` ON `Customer`(`portalEmail`); + +-- AddForeignKey +ALTER TABLE `CustomerRepresentative` ADD CONSTRAINT `CustomerRepresentative_customerId_fkey` FOREIGN KEY (`customerId`) REFERENCES `Customer`(`id`) ON DELETE CASCADE ON UPDATE CASCADE; + +-- AddForeignKey +ALTER TABLE `CustomerRepresentative` ADD CONSTRAINT `CustomerRepresentative_representativeId_fkey` FOREIGN KEY (`representativeId`) REFERENCES `Customer`(`id`) ON DELETE CASCADE ON UPDATE CASCADE; + +-- AddForeignKey +ALTER TABLE `StressfreiEmail` ADD CONSTRAINT `StressfreiEmail_customerId_fkey` FOREIGN KEY (`customerId`) REFERENCES `Customer`(`id`) ON DELETE CASCADE ON UPDATE CASCADE; + +-- AddForeignKey +ALTER TABLE `CachedEmail` ADD CONSTRAINT `CachedEmail_stressfreiEmailId_fkey` FOREIGN KEY (`stressfreiEmailId`) REFERENCES `StressfreiEmail`(`id`) ON DELETE CASCADE ON UPDATE CASCADE; + +-- AddForeignKey +ALTER TABLE `CachedEmail` ADD CONSTRAINT `CachedEmail_contractId_fkey` FOREIGN KEY (`contractId`) REFERENCES `Contract`(`id`) ON DELETE SET NULL ON UPDATE CASCADE; + +-- AddForeignKey +ALTER TABLE `Contract` ADD CONSTRAINT `Contract_stressfreiEmailId_fkey` FOREIGN KEY (`stressfreiEmailId`) REFERENCES `StressfreiEmail`(`id`) ON DELETE SET NULL ON UPDATE CASCADE; + +-- AddForeignKey +ALTER TABLE `ContractTask` ADD CONSTRAINT `ContractTask_contractId_fkey` FOREIGN KEY (`contractId`) REFERENCES `Contract`(`id`) ON DELETE CASCADE ON UPDATE CASCADE; + +-- AddForeignKey +ALTER TABLE `ContractTaskSubtask` ADD CONSTRAINT `ContractTaskSubtask_taskId_fkey` FOREIGN KEY (`taskId`) REFERENCES `ContractTask`(`id`) ON DELETE CASCADE ON UPDATE CASCADE; diff --git a/backend/prisma/migrations/20260130233909_add_token_invalidation/migration.sql b/backend/prisma/migrations/20260130233909_add_token_invalidation/migration.sql new file mode 100644 index 00000000..064972fb --- /dev/null +++ b/backend/prisma/migrations/20260130233909_add_token_invalidation/migration.sql @@ -0,0 +1,2 @@ +-- AlterTable +ALTER TABLE `User` ADD COLUMN `tokenInvalidatedAt` DATETIME(3) NULL; diff --git a/backend/prisma/restore-data.ts b/backend/prisma/restore-data.ts new file mode 100644 index 00000000..53ab9822 --- /dev/null +++ b/backend/prisma/restore-data.ts @@ -0,0 +1,486 @@ +/** + * Datenbank-Restore Script + * + * Stellt Daten aus einem JSON-Backup wieder her. + * + * Verwendung: + * npx ts-node prisma/restore-data.ts [backup-ordner] + * + * Beispiele: + * npx ts-node prisma/restore-data.ts # Letztes Backup + * npx ts-node prisma/restore-data.ts 2025-01-31_14-30-00 # Bestimmtes Backup + * + * WICHTIG: Führe vorher 'npx prisma migrate deploy' oder 'npx prisma db push' aus! + */ + +import { PrismaClient } from '@prisma/client'; +import * as fs from 'fs'; +import * as path from 'path'; + +const prisma = new PrismaClient(); + +// Hilfsfunktion: JSON-Datei lesen +function readJsonFile(filePath: string): T[] { + if (!fs.existsSync(filePath)) { + return []; + } + const content = fs.readFileSync(filePath, 'utf-8'); + return JSON.parse(content); +} + +// Hilfsfunktion: Datum-Strings zu Date-Objekten konvertieren +function convertDates(obj: any): any { + if (obj === null || obj === undefined) return obj; + if (typeof obj === 'string') { + // ISO-Datumsformat erkennen + if (/^\d{4}-\d{2}-\d{2}T\d{2}:\d{2}:\d{2}/.test(obj)) { + return new Date(obj); + } + return obj; + } + if (Array.isArray(obj)) { + return obj.map(convertDates); + } + if (typeof obj === 'object') { + const result: any = {}; + for (const [key, value] of Object.entries(obj)) { + result[key] = convertDates(value); + } + return result; + } + return obj; +} + +async function main() { + // Backup-Ordner bestimmen + const backupsDir = path.join(__dirname, 'backups'); + let backupName = process.argv[2]; + + if (!backupName) { + // Neuestes Backup finden + if (!fs.existsSync(backupsDir)) { + console.error('❌ Kein Backup-Ordner gefunden!'); + process.exit(1); + } + const backups = fs.readdirSync(backupsDir) + .filter(f => fs.statSync(path.join(backupsDir, f)).isDirectory()) + .sort() + .reverse(); + + if (backups.length === 0) { + console.error('❌ Keine Backups gefunden!'); + process.exit(1); + } + backupName = backups[0]; + console.log(`📦 Verwende neuestes Backup: ${backupName}`); + } + + const backupDir = path.join(backupsDir, backupName); + + if (!fs.existsSync(backupDir)) { + console.error(`❌ Backup-Ordner nicht gefunden: ${backupDir}`); + process.exit(1); + } + + // Backup-Info lesen + const infoPath = path.join(backupDir, '_backup-info.json'); + if (fs.existsSync(infoPath)) { + const info = JSON.parse(fs.readFileSync(infoPath, 'utf-8')); + console.log(`\n📅 Backup vom: ${new Date(info.timestamp).toLocaleString('de-DE')}`); + console.log(`📊 ${info.totalRecords} Datensätze in ${info.tables.filter((t: any) => t.count > 0).length} Tabellen\n`); + } + + console.log(`🔄 Starte Wiederherstellung aus: ${backupDir}\n`); + + // Foreign Key Checks deaktivieren für MySQL + await prisma.$executeRawUnsafe('SET FOREIGN_KEY_CHECKS = 0'); + + try { + // Tabellen in Abhängigkeitsreihenfolge wiederherstellen + const restoreOrder = [ + // Level 0: Keine Abhängigkeiten + { + name: 'Permission', + restore: async (data: any[]) => { + for (const item of data) { + await prisma.permission.upsert({ + where: { id: item.id }, + update: convertDates(item), + create: convertDates(item), + }); + } + }, + }, + { + name: 'Role', + restore: async (data: any[]) => { + for (const item of data) { + await prisma.role.upsert({ + where: { id: item.id }, + update: convertDates(item), + create: convertDates(item), + }); + } + }, + }, + { + name: 'SalesPlatform', + restore: async (data: any[]) => { + for (const item of data) { + await prisma.salesPlatform.upsert({ + where: { id: item.id }, + update: convertDates(item), + create: convertDates(item), + }); + } + }, + }, + { + name: 'ContractCategory', + restore: async (data: any[]) => { + for (const item of data) { + await prisma.contractCategory.upsert({ + where: { id: item.id }, + update: convertDates(item), + create: convertDates(item), + }); + } + }, + }, + { + name: 'CancellationPeriod', + restore: async (data: any[]) => { + for (const item of data) { + await prisma.cancellationPeriod.upsert({ + where: { id: item.id }, + update: convertDates(item), + create: convertDates(item), + }); + } + }, + }, + { + name: 'ContractDuration', + restore: async (data: any[]) => { + for (const item of data) { + await prisma.contractDuration.upsert({ + where: { id: item.id }, + update: convertDates(item), + create: convertDates(item), + }); + } + }, + }, + { + name: 'AppSetting', + restore: async (data: any[]) => { + for (const item of data) { + await prisma.appSetting.upsert({ + where: { id: item.id }, + update: convertDates(item), + create: convertDates(item), + }); + } + }, + }, + { + name: 'EmailProviderConfig', + restore: async (data: any[]) => { + for (const item of data) { + await prisma.emailProviderConfig.upsert({ + where: { id: item.id }, + update: convertDates(item), + create: convertDates(item), + }); + } + }, + }, + { + name: 'EnergyProvider', + restore: async (data: any[]) => { + for (const item of data) { + await prisma.energyProvider.upsert({ + where: { id: item.id }, + update: convertDates(item), + create: convertDates(item), + }); + } + }, + }, + { + name: 'TelecomProvider', + restore: async (data: any[]) => { + for (const item of data) { + await prisma.telecomProvider.upsert({ + where: { id: item.id }, + update: convertDates(item), + create: convertDates(item), + }); + } + }, + }, + + // Level 1 + { + name: 'RolePermission', + restore: async (data: any[]) => { + for (const item of data) { + await prisma.rolePermission.upsert({ + where: { roleId_permissionId: { roleId: item.roleId, permissionId: item.permissionId } }, + update: {}, + create: convertDates(item), + }); + } + }, + }, + { + name: 'User', + restore: async (data: any[]) => { + for (const item of data) { + await prisma.user.upsert({ + where: { id: item.id }, + update: convertDates(item), + create: convertDates(item), + }); + } + }, + }, + { + name: 'Customer', + restore: async (data: any[]) => { + for (const item of data) { + await prisma.customer.upsert({ + where: { id: item.id }, + update: convertDates(item), + create: convertDates(item), + }); + } + }, + }, + { + name: 'Tariff', + restore: async (data: any[]) => { + for (const item of data) { + await prisma.tariff.upsert({ + where: { id: item.id }, + update: convertDates(item), + create: convertDates(item), + }); + } + }, + }, + + // Level 2 + { + name: 'UserRole', + restore: async (data: any[]) => { + for (const item of data) { + await prisma.userRole.upsert({ + where: { userId_roleId: { userId: item.userId, roleId: item.roleId } }, + update: {}, + create: convertDates(item), + }); + } + }, + }, + { + name: 'CustomerRepresentative', + restore: async (data: any[]) => { + for (const item of data) { + await prisma.customerRepresentative.upsert({ + where: { id: item.id }, + update: convertDates(item), + create: convertDates(item), + }); + } + }, + }, + { + name: 'StressfreiEmail', + restore: async (data: any[]) => { + for (const item of data) { + await prisma.stressfreiEmail.upsert({ + where: { id: item.id }, + update: convertDates(item), + create: convertDates(item), + }); + } + }, + }, + { + name: 'Contract', + restore: async (data: any[]) => { + for (const item of data) { + await prisma.contract.upsert({ + where: { id: item.id }, + update: convertDates(item), + create: convertDates(item), + }); + } + }, + }, + { + name: 'Meter', + restore: async (data: any[]) => { + for (const item of data) { + await prisma.meter.upsert({ + where: { id: item.id }, + update: convertDates(item), + create: convertDates(item), + }); + } + }, + }, + + // Level 3 + { + name: 'CachedEmail', + restore: async (data: any[]) => { + for (const item of data) { + await prisma.cachedEmail.upsert({ + where: { id: item.id }, + update: convertDates(item), + create: convertDates(item), + }); + } + }, + }, + { + name: 'ContractTask', + restore: async (data: any[]) => { + for (const item of data) { + await prisma.contractTask.upsert({ + where: { id: item.id }, + update: convertDates(item), + create: convertDates(item), + }); + } + }, + }, + { + name: 'MeterReading', + restore: async (data: any[]) => { + for (const item of data) { + await prisma.meterReading.upsert({ + where: { id: item.id }, + update: convertDates(item), + create: convertDates(item), + }); + } + }, + }, + { + name: 'ContractNote', + restore: async (data: any[]) => { + for (const item of data) { + await prisma.contractNote.upsert({ + where: { id: item.id }, + update: convertDates(item), + create: convertDates(item), + }); + } + }, + }, + { + name: 'ContractDocument', + restore: async (data: any[]) => { + for (const item of data) { + await prisma.contractDocument.upsert({ + where: { id: item.id }, + update: convertDates(item), + create: convertDates(item), + }); + } + }, + }, + + // Level 4 + { + name: 'ContractTaskSubtask', + restore: async (data: any[]) => { + for (const item of data) { + await prisma.contractTaskSubtask.upsert({ + where: { id: item.id }, + update: convertDates(item), + create: convertDates(item), + }); + } + }, + }, + + // Vertragsdetails + { + name: 'EnergyContractDetails', + restore: async (data: any[]) => { + for (const item of data) { + await prisma.energyContractDetails.upsert({ + where: { id: item.id }, + update: convertDates(item), + create: convertDates(item), + }); + } + }, + }, + { + name: 'TelecomContractDetails', + restore: async (data: any[]) => { + for (const item of data) { + await prisma.telecomContractDetails.upsert({ + where: { id: item.id }, + update: convertDates(item), + create: convertDates(item), + }); + } + }, + }, + { + name: 'CarInsuranceDetails', + restore: async (data: any[]) => { + for (const item of data) { + await prisma.carInsuranceDetails.upsert({ + where: { id: item.id }, + update: convertDates(item), + create: convertDates(item), + }); + } + }, + }, + ]; + + let totalRestored = 0; + + for (const table of restoreOrder) { + const filePath = path.join(backupDir, `${table.name}.json`); + const data = readJsonFile(filePath); + + if (data.length === 0) { + console.log(`⚪ ${table.name}: Keine Daten`); + continue; + } + + try { + await table.restore(data); + totalRestored += data.length; + console.log(`✅ ${table.name}: ${data.length} Einträge wiederhergestellt`); + } catch (error: any) { + console.log(`⚠️ ${table.name}: Fehler - ${error.message?.slice(0, 80)}`); + } + } + + console.log(`\n✅ Wiederherstellung abgeschlossen!`); + console.log(` 📊 ${totalRestored} Datensätze wiederhergestellt\n`); + + } finally { + // Foreign Key Checks wieder aktivieren + await prisma.$executeRawUnsafe('SET FOREIGN_KEY_CHECKS = 1'); + } +} + +main() + .catch((e) => { + console.error('❌ Wiederherstellung fehlgeschlagen:', e); + process.exit(1); + }) + .finally(async () => { + await prisma.$disconnect(); + }); diff --git a/backend/prisma/schema.prisma b/backend/prisma/schema.prisma index 95322474..0b8152af 100644 --- a/backend/prisma/schema.prisma +++ b/backend/prisma/schema.prisma @@ -20,17 +20,18 @@ model AppSetting { // ==================== USERS & AUTH ==================== model User { - id Int @id @default(autoincrement()) - email String @unique - password String - firstName String - lastName String - isActive Boolean @default(true) - customerId Int? @unique - customer Customer? @relation(fields: [customerId], references: [id]) - roles UserRole[] - createdAt DateTime @default(now()) - updatedAt DateTime @updatedAt + id Int @id @default(autoincrement()) + email String @unique + password String + firstName String + lastName String + isActive Boolean @default(true) + tokenInvalidatedAt DateTime? // Zeitpunkt ab dem alle Tokens ungültig sind (für Zwangslogout bei Rechteänderung) + customerId Int? @unique + customer Customer? @relation(fields: [customerId], references: [id]) + roles UserRole[] + createdAt DateTime @default(now()) + updatedAt DateTime @updatedAt } model Role { @@ -216,6 +217,13 @@ enum EmailProviderType { DIRECTADMIN } +// Verschlüsselungstyp für E-Mail-Verbindungen +enum MailEncryption { + SSL // Implicit SSL/TLS (Ports 465/993) - Verschlüsselung von Anfang an + STARTTLS // STARTTLS (Ports 587/143) - Startet unverschlüsselt, dann Upgrade + NONE // Keine Verschlüsselung (Ports 25/143) +} + model EmailProviderConfig { id Int @id @default(autoincrement()) name String @unique // z.B. "Plesk Hauptserver" @@ -226,6 +234,18 @@ model EmailProviderConfig { passwordEncrypted String? // Passwort (verschlüsselt) domain String // Domain für E-Mails (z.B. stressfrei-wechseln.de) defaultForwardEmail String? // Standard-Weiterleitungsadresse (unsere eigene) + + // IMAP/SMTP-Server für E-Mail-Client (optional, default: mail.{domain}) + imapServer String? // z.B. "mail.stressfrei-wechseln.de" + imapPort Int? @default(993) + smtpServer String? + smtpPort Int? @default(465) + + // Verschlüsselungs-Einstellungen + imapEncryption MailEncryption @default(SSL) // SSL, STARTTLS oder NONE + smtpEncryption MailEncryption @default(SSL) // SSL, STARTTLS oder NONE + allowSelfSignedCerts Boolean @default(false) // Selbstsignierte Zertifikate erlauben + isActive Boolean @default(true) isDefault Boolean @default(false) // Standard-Provider createdAt DateTime @default(now()) @@ -235,19 +255,82 @@ model EmailProviderConfig { // ==================== STRESSFREI-WECHSELN EMAIL ADDRESSES ==================== model StressfreiEmail { - id Int @id @default(autoincrement()) - customerId Int - customer Customer @relation(fields: [customerId], references: [id], onDelete: Cascade) - email String // Die Weiterleitungs-E-Mail-Adresse - platform String? // Für welche Plattform (z.B. "Freenet", "Klarmobil") - notes String? @db.Text // Optionale Notizen - isActive Boolean @default(true) - isProvisioned Boolean @default(false) // Wurde bei Provider angelegt? - provisionedAt DateTime? // Wann wurde provisioniert? - provisionError String? @db.Text // Fehlermeldung falls Provisionierung fehlschlug - contracts Contract[] // Verträge die diese E-Mail als Benutzername verwenden - createdAt DateTime @default(now()) - updatedAt DateTime @updatedAt + id Int @id @default(autoincrement()) + customerId Int + customer Customer @relation(fields: [customerId], references: [id], onDelete: Cascade) + email String // Die Weiterleitungs-E-Mail-Adresse + platform String? // Für welche Plattform (z.B. "Freenet", "Klarmobil") + notes String? @db.Text // Optionale Notizen + isActive Boolean @default(true) + isProvisioned Boolean @default(false) // Wurde bei Provider angelegt? + provisionedAt DateTime? // Wann wurde provisioniert? + provisionError String? @db.Text // Fehlermeldung falls Provisionierung fehlschlug + + // Mailbox-Zugangsdaten (für IMAP/SMTP-Zugang) + hasMailbox Boolean @default(false) // Hat echte Mailbox (nicht nur Weiterleitung)? + emailPasswordEncrypted String? // Verschlüsseltes Mailbox-Passwort (AES-256-GCM) + + contracts Contract[] // Verträge die diese E-Mail als Benutzername verwenden + cachedEmails CachedEmail[] // Gecachte E-Mails aus dieser Mailbox + createdAt DateTime @default(now()) + updatedAt DateTime @updatedAt +} + +// ==================== CACHED EMAILS (E-Mail-Client) ==================== + +enum EmailFolder { + INBOX + SENT +} + +model CachedEmail { + id Int @id @default(autoincrement()) + stressfreiEmailId Int + stressfreiEmail StressfreiEmail @relation(fields: [stressfreiEmailId], references: [id], onDelete: Cascade) + + // Ordner (Posteingang oder Gesendet) + folder EmailFolder @default(INBOX) + + // IMAP-Identifikation + messageId String // RFC 5322 Message-ID + uid Int // IMAP UID (für Synchronisierung, bei SENT = 0) + + // E-Mail-Metadaten + subject String? + fromAddress String + fromName String? + toAddresses String @db.Text // JSON Array + ccAddresses String? @db.Text // JSON Array + receivedAt DateTime + + // Inhalt + textBody String? @db.LongText + htmlBody String? @db.LongText + hasAttachments Boolean @default(false) + attachmentNames String? @db.Text // JSON Array + + // Vertragszuordnung + contractId Int? + contract Contract? @relation(fields: [contractId], references: [id], onDelete: SetNull) + assignedAt DateTime? + assignedBy Int? // User ID der die Zuordnung gemacht hat + isAutoAssigned Boolean @default(false) // true = automatisch beim Senden aus Vertrag + + // Flags + isRead Boolean @default(false) + isStarred Boolean @default(false) + + // Papierkorb + isDeleted Boolean @default(false) // Im Papierkorb? + deletedAt DateTime? // Wann gelöscht? + + createdAt DateTime @default(now()) + updatedAt DateTime @updatedAt + + @@unique([stressfreiEmailId, messageId, folder]) // Folder hinzugefügt: gleiche MessageID kann in INBOX und SENT existieren + @@index([contractId]) + @@index([stressfreiEmailId, folder, receivedAt]) + @@index([stressfreiEmailId, isDeleted]) // Für Papierkorb-Abfragen } // ==================== METERS (Energy) ==================== @@ -465,6 +548,7 @@ model Contract { carInsuranceDetails CarInsuranceDetails? tasks ContractTask[] + assignedEmails CachedEmail[] // Zugeordnete E-Mails aus dem E-Mail-Client createdAt DateTime @default(now()) updatedAt DateTime @updatedAt diff --git a/backend/prisma/seed.ts b/backend/prisma/seed.ts index 03ba3de9..bf5ce4da 100644 --- a/backend/prisma/seed.ts +++ b/backend/prisma/seed.ts @@ -6,17 +6,31 @@ const prisma = new PrismaClient(); async function main() { console.log('Seeding database...'); - // Create permissions - const resources = ['customers', 'contracts', 'users', 'platforms', 'providers', 'developer']; - const actions = ['create', 'read', 'update', 'delete', 'access']; + // ==================== PERMISSIONS ==================== + // Ressourcen mit ihren erlaubten Aktionen + const resourcePermissions: Record = { + // Haupt-Ressourcen (CRUD) + customers: ['create', 'read', 'update', 'delete'], + contracts: ['create', 'read', 'update', 'delete'], + users: ['create', 'read', 'update', 'delete'], + platforms: ['create', 'read', 'update', 'delete'], + providers: ['create', 'read', 'update', 'delete'], + tariffs: ['create', 'read', 'update', 'delete'], + // Konfiguration (CRUD) + 'cancellation-periods': ['create', 'read', 'update', 'delete'], + 'contract-durations': ['create', 'read', 'update', 'delete'], + 'contract-categories': ['create', 'read', 'update', 'delete'], + 'email-providers': ['create', 'read', 'update', 'delete'], + // Einstellungen (nur lesen/ändern) + settings: ['read', 'update'], + // Spezial-Permissions + developer: ['access'], + emails: ['delete'], + }; const permissions: { resource: string; action: string }[] = []; - for (const resource of resources) { + for (const [resource, actions] of Object.entries(resourcePermissions)) { for (const action of actions) { - // developer nur mit 'access' action - if (resource === 'developer' && action !== 'access') continue; - // andere resources ohne 'access' action - if (resource !== 'developer' && action === 'access') continue; permissions.push({ resource, action }); } } @@ -29,7 +43,7 @@ async function main() { }); } - console.log('Permissions created'); + console.log(`Permissions created (${permissions.length} total)`); // Get all permissions const allPermissions = await prisma.permission.findMany(); @@ -63,14 +77,34 @@ async function main() { }, }); - // Employee - full access to customers, contracts, read platforms and providers + // Developer - ALL permissions including developer:access + const developerRole = await prisma.role.upsert({ + where: { name: 'Developer' }, + update: {}, + create: { + name: 'Developer', + description: 'Voller Zugriff inkl. Entwickler-Tools', + permissions: { + create: allPermissions.map((p) => ({ permissionId: p.id })), + }, + }, + }); + + // Employee - full access to customers, contracts, read access to lookup tables const employeePermIds = allPermissions .filter( (p) => p.resource === 'customers' || p.resource === 'contracts' || - (p.resource === 'platforms' && p.action === 'read') || - (p.resource === 'providers' && p.action === 'read') + // Read-only Zugriff auf Stammdaten und Konfiguration + (p.action === 'read' && [ + 'platforms', + 'providers', + 'tariffs', + 'cancellation-periods', + 'contract-durations', + 'contract-categories', + ].includes(p.resource)) ) .map((p) => p.id); @@ -86,10 +120,20 @@ async function main() { }, }); - // Read-only employee - const readOnlyPermIds = [customerReadPerm?.id, contractReadPerm?.id, platformReadPerm?.id, providerReadPerm?.id].filter( - (id): id is number => id !== undefined - ); + // Read-only employee - read access to main entities and lookup tables + const readOnlyResources = [ + 'customers', + 'contracts', + 'platforms', + 'providers', + 'tariffs', + 'cancellation-periods', + 'contract-durations', + 'contract-categories', + ]; + const readOnlyPermIds = allPermissions + .filter((p) => p.action === 'read' && readOnlyResources.includes(p.resource)) + .map((p) => p.id); const readOnlyRole = await prisma.role.upsert({ where: { name: 'Mitarbeiter (Nur-Lesen)' }, @@ -149,15 +193,76 @@ async function main() { console.log('Sales platforms created'); + // ==================== STANDARD PROVIDERS ==================== + const providers = [ + { + name: 'Vodafone', + portalUrl: 'https://www.vodafone.de/meinvodafone/account/login', + usernameFieldName: 'username', + passwordFieldName: 'password', + }, + { + name: 'Klarmobil', + portalUrl: 'https://www.klarmobil.de/login', + usernameFieldName: 'username', + passwordFieldName: 'password', + }, + { + name: 'Otelo', + portalUrl: 'https://www.otelo.de/mein-otelo/login', + usernameFieldName: 'username', + passwordFieldName: 'password', + }, + { + name: 'Congstar', + portalUrl: 'https://www.congstar.de/login/', + usernameFieldName: 'username', + passwordFieldName: 'password', + }, + { + name: 'Telekom', + portalUrl: 'https://www.telekom.de/kundencenter/startseite', + usernameFieldName: 'username', + passwordFieldName: 'password', + }, + { + name: 'O2', + portalUrl: 'https://www.o2online.de/ecare/selfcare', + usernameFieldName: 'username', + passwordFieldName: 'password', + }, + { + name: '1&1', + portalUrl: 'https://control-center.1und1.de/', + usernameFieldName: 'username', + passwordFieldName: 'password', + }, + ]; + + for (const provider of providers) { + await prisma.provider.upsert({ + where: { name: provider.name }, + update: { + portalUrl: provider.portalUrl, + usernameFieldName: provider.usernameFieldName, + passwordFieldName: provider.passwordFieldName, + }, + create: { ...provider, isActive: true }, + }); + } + + console.log('Providers created'); + // Create contract categories (matching existing enum values) const contractCategories = [ { code: 'ELECTRICITY', name: 'Strom', icon: 'Zap', color: '#FFC107', sortOrder: 1 }, { code: 'GAS', name: 'Gas', icon: 'Flame', color: '#FF5722', sortOrder: 2 }, { code: 'DSL', name: 'DSL', icon: 'Wifi', color: '#2196F3', sortOrder: 3 }, { code: 'FIBER', name: 'Glasfaser', icon: 'Cable', color: '#9C27B0', sortOrder: 4 }, - { code: 'MOBILE', name: 'Mobilfunk', icon: 'Smartphone', color: '#4CAF50', sortOrder: 5 }, - { code: 'TV', name: 'TV', icon: 'Tv', color: '#E91E63', sortOrder: 6 }, - { code: 'CAR_INSURANCE', name: 'KFZ-Versicherung', icon: 'Car', color: '#607D8B', sortOrder: 7 }, + { code: 'CABLE', name: 'Kabel Internet (Coax)', icon: 'Cable', color: '#00BCD4', sortOrder: 5 }, + { code: 'MOBILE', name: 'Mobilfunk', icon: 'Smartphone', color: '#4CAF50', sortOrder: 6 }, + { code: 'TV', name: 'TV', icon: 'Tv', color: '#E91E63', sortOrder: 7 }, + { code: 'CAR_INSURANCE', name: 'KFZ-Versicherung', icon: 'Car', color: '#607D8B', sortOrder: 8 }, ]; for (const category of contractCategories) { @@ -170,6 +275,77 @@ async function main() { console.log('Contract categories created'); + // ==================== CANCELLATION PERIODS ==================== + const cancellationPeriods = [ + { code: '14D', description: '14 Tage' }, + { code: '1M', description: '1 Monat' }, + { code: '2M', description: '2 Monate' }, + { code: '3M', description: '3 Monate' }, + { code: '6M', description: '6 Monate' }, + { code: '12M', description: '12 Monate' }, + { code: '1W', description: '1 Woche' }, + { code: '2W', description: '2 Wochen' }, + { code: '4W', description: '4 Wochen' }, + { code: '6W', description: '6 Wochen' }, + ]; + + for (const period of cancellationPeriods) { + await prisma.cancellationPeriod.upsert({ + where: { code: period.code }, + update: { description: period.description }, + create: period, + }); + } + + console.log('Cancellation periods created'); + + // ==================== CONTRACT DURATIONS ==================== + const contractDurations = [ + { code: '1M', description: '1 Monat' }, + { code: '3M', description: '3 Monate' }, + { code: '6M', description: '6 Monate' }, + { code: '12M', description: '12 Monate' }, + { code: '24M', description: '24 Monate' }, + { code: '36M', description: '36 Monate' }, + { code: '1J', description: '1 Jahr' }, + { code: '2J', description: '2 Jahre' }, + { code: '3J', description: '3 Jahre' }, + { code: '4J', description: '4 Jahre' }, + { code: '5J', description: '5 Jahre' }, + { code: 'UNBEFRISTET', description: 'Unbefristet' }, + ]; + + for (const duration of contractDurations) { + await prisma.contractDuration.upsert({ + where: { code: duration.code }, + update: { description: duration.description }, + create: duration, + }); + } + + console.log('Contract durations created'); + + // ==================== APP SETTINGS ==================== + const appSettings = [ + // Cockpit-Einstellungen (Fristen-Ampel) + { key: 'deadlineCriticalDays', value: '14' }, // Rot: <= 14 Tage + { key: 'deadlineWarningDays', value: '42' }, // Gelb: <= 42 Tage + { key: 'deadlineOkDays', value: '90' }, // Grün: <= 90 Tage + // Allgemeine Einstellungen + { key: 'companyName', value: 'OpenCRM' }, + { key: 'defaultEmailDomain', value: 'stressfrei-wechseln.de' }, + ]; + + for (const setting of appSettings) { + await prisma.appSetting.upsert({ + where: { key: setting.key }, + update: {}, // Bestehende Werte nicht überschreiben + create: setting, + }); + } + + console.log('App settings created'); + console.log('Seeding completed!'); } diff --git a/backend/src/controllers/backup.controller.ts b/backend/src/controllers/backup.controller.ts new file mode 100644 index 00000000..c613256f --- /dev/null +++ b/backend/src/controllers/backup.controller.ts @@ -0,0 +1,169 @@ +import { Request, Response } from 'express'; +import * as backupService from '../services/backup.service.js'; + +/** + * Liste aller Backups abrufen + * GET /api/settings/backups + */ +export async function listBackups(req: Request, res: Response) { + try { + const backups = await backupService.listBackups(); + res.json({ data: backups }); + } catch (error: any) { + res.status(500).json({ error: 'Fehler beim Laden der Backups', details: error.message }); + } +} + +/** + * Neues Backup erstellen + * POST /api/settings/backup + */ +export async function createBackup(req: Request, res: Response) { + try { + const result = await backupService.createBackup(); + + if (result.success) { + res.json({ data: { backupName: result.backupName }, message: 'Backup erfolgreich erstellt' }); + } else { + res.status(500).json({ error: 'Backup fehlgeschlagen', details: result.error }); + } + } catch (error: any) { + res.status(500).json({ error: 'Fehler beim Erstellen des Backups', details: error.message }); + } +} + +/** + * Backup wiederherstellen + * POST /api/settings/backup/:name/restore + */ +export async function restoreBackup(req: Request, res: Response) { + try { + const { name } = req.params; + + if (!name) { + return res.status(400).json({ error: 'Backup-Name erforderlich' }); + } + + const result = await backupService.restoreBackup(name); + + if (result.success) { + res.json({ + data: { + restoredRecords: result.restoredRecords, + restoredFiles: result.restoredFiles, + }, + message: `${result.restoredRecords} Datensätze und ${result.restoredFiles || 0} Dateien wiederhergestellt`, + }); + } else { + res.status(500).json({ error: 'Wiederherstellung fehlgeschlagen', details: result.error }); + } + } catch (error: any) { + res.status(500).json({ error: 'Fehler bei der Wiederherstellung', details: error.message }); + } +} + +/** + * Backup löschen + * DELETE /api/settings/backup/:name + */ +export async function deleteBackup(req: Request, res: Response) { + try { + const { name } = req.params; + + if (!name) { + return res.status(400).json({ error: 'Backup-Name erforderlich' }); + } + + const result = await backupService.deleteBackup(name); + + if (result.success) { + res.json({ message: 'Backup gelöscht' }); + } else { + res.status(500).json({ error: 'Löschen fehlgeschlagen', details: result.error }); + } + } catch (error: any) { + res.status(500).json({ error: 'Fehler beim Löschen des Backups', details: error.message }); + } +} + +/** + * Backup als ZIP herunterladen + * GET /api/settings/backup/:name/download + */ +export async function downloadBackup(req: Request, res: Response) { + try { + const { name } = req.params; + + if (!name) { + return res.status(400).json({ error: 'Backup-Name erforderlich' }); + } + + const result = await backupService.createBackupZip(name); + + if ('error' in result) { + return res.status(404).json({ error: result.error }); + } + + // Response-Header setzen + res.setHeader('Content-Type', 'application/zip'); + res.setHeader('Content-Disposition', `attachment; filename="${result.filename}"`); + + // Archiver zum Response pipen + result.stream.pipe(res); + + // Archiver finalisieren (startet das Schreiben) + result.stream.finalize(); + } catch (error: any) { + res.status(500).json({ error: 'Fehler beim Download', details: error.message }); + } +} + +/** + * Backup-ZIP hochladen + * POST /api/settings/backup/upload + */ +export async function uploadBackup(req: Request, res: Response) { + try { + if (!req.file) { + return res.status(400).json({ error: 'Keine Datei hochgeladen' }); + } + + // Prüfen ob es eine ZIP-Datei ist + if (!req.file.originalname.endsWith('.zip')) { + return res.status(400).json({ error: 'Nur ZIP-Dateien sind erlaubt' }); + } + + const result = await backupService.uploadBackupZip(req.file.buffer); + + if (result.success) { + res.json({ + data: { backupName: result.backupName }, + message: 'Backup erfolgreich hochgeladen', + }); + } else { + res.status(400).json({ error: 'Upload fehlgeschlagen', details: result.error }); + } + } catch (error: any) { + res.status(500).json({ error: 'Fehler beim Upload', details: error.message }); + } +} + +/** + * Werkseinstellungen - Alle Daten löschen + * POST /api/settings/factory-reset + */ +export async function factoryReset(req: Request, res: Response) { + try { + const result = await backupService.factoryReset(); + + if (result.success) { + res.json({ + message: 'Werkseinstellungen wiederhergestellt. Bitte melden Sie sich mit admin@admin.com / admin an.', + }); + } else { + res.status(500).json({ error: 'Werkseinstellungen fehlgeschlagen', details: result.error }); + } + } catch (error: any) { + res.status(500).json({ error: 'Fehler bei Werkseinstellungen', details: error.message }); + } +} diff --git a/backend/src/controllers/cachedEmail.controller.ts b/backend/src/controllers/cachedEmail.controller.ts new file mode 100644 index 00000000..52b9921f --- /dev/null +++ b/backend/src/controllers/cachedEmail.controller.ts @@ -0,0 +1,805 @@ +// ==================== CACHED EMAIL CONTROLLER ==================== + +import { Request, Response } from 'express'; +import * as cachedEmailService from '../services/cachedEmail.service.js'; +import * as stressfreiEmailService from '../services/stressfreiEmail.service.js'; +import { sendEmail, SmtpCredentials, SendEmailParams, EmailAttachment } from '../services/smtpService.js'; +import { fetchAttachment, appendToSent, ImapCredentials } from '../services/imapService.js'; +import { getImapSmtpSettings } from '../services/emailProvider/emailProviderService.js'; +import { decrypt } from '../utils/encryption.js'; +import { ApiResponse } from '../types/index.js'; + +// ==================== E-MAIL LIST ==================== + +// E-Mails für einen Kunden abrufen +export async function getEmailsForCustomer(req: Request, res: Response): Promise { + try { + const customerId = parseInt(req.params.customerId); + const stressfreiEmailId = req.query.accountId ? parseInt(req.query.accountId as string) : undefined; + const folder = req.query.folder as string | undefined; // INBOX oder SENT + const limit = req.query.limit ? parseInt(req.query.limit as string) : 50; + const offset = req.query.offset ? parseInt(req.query.offset as string) : 0; + + const emails = await cachedEmailService.getCachedEmails({ + customerId, + stressfreiEmailId, + folder, + limit, + offset, + includeBody: false, + }); + + res.json({ success: true, data: emails } as ApiResponse); + } catch (error) { + console.error('getEmailsForCustomer error:', error); + res.status(500).json({ + success: false, + error: 'Fehler beim Laden der E-Mails', + } as ApiResponse); + } +} + +// E-Mails für einen Vertrag abrufen +export async function getEmailsForContract(req: Request, res: Response): Promise { + try { + const contractId = parseInt(req.params.contractId); + const folder = req.query.folder as string | undefined; // INBOX oder SENT + const limit = req.query.limit ? parseInt(req.query.limit as string) : 50; + const offset = req.query.offset ? parseInt(req.query.offset as string) : 0; + + const emails = await cachedEmailService.getCachedEmails({ + contractId, + folder, + limit, + offset, + includeBody: false, + }); + + res.json({ success: true, data: emails } as ApiResponse); + } catch (error) { + console.error('getEmailsForContract error:', error); + res.status(500).json({ + success: false, + error: 'Fehler beim Laden der Vertrags-E-Mails', + } as ApiResponse); + } +} + +// ==================== SINGLE EMAIL ==================== + +// Einzelne E-Mail abrufen (mit Body) +export async function getEmail(req: Request, res: Response): Promise { + try { + const id = parseInt(req.params.id); + const email = await cachedEmailService.getCachedEmailById(id); + + if (!email) { + res.status(404).json({ + success: false, + error: 'E-Mail nicht gefunden', + } as ApiResponse); + return; + } + + // Als gelesen markieren + await cachedEmailService.markEmailAsRead(id); + + res.json({ success: true, data: { ...email, isRead: true } } as ApiResponse); + } catch (error) { + console.error('getEmail error:', error); + res.status(500).json({ + success: false, + error: 'Fehler beim Laden der E-Mail', + } as ApiResponse); + } +} + +// E-Mail als gelesen/ungelesen markieren +export async function markAsRead(req: Request, res: Response): Promise { + try { + const id = parseInt(req.params.id); + const { isRead } = req.body; + + if (isRead) { + await cachedEmailService.markEmailAsRead(id); + } else { + await cachedEmailService.markEmailAsUnread(id); + } + + res.json({ success: true } as ApiResponse); + } catch (error) { + console.error('markAsRead error:', error); + res.status(500).json({ + success: false, + error: 'Fehler beim Markieren der E-Mail', + } as ApiResponse); + } +} + +// E-Mail Stern umschalten +export async function toggleStar(req: Request, res: Response): Promise { + try { + const id = parseInt(req.params.id); + const isStarred = await cachedEmailService.toggleEmailStar(id); + + res.json({ success: true, data: { isStarred } } as ApiResponse); + } catch (error) { + console.error('toggleStar error:', error); + res.status(500).json({ + success: false, + error: 'Fehler beim Ändern des Sterns', + } as ApiResponse); + } +} + +// ==================== CONTRACT ASSIGNMENT ==================== + +// E-Mail einem Vertrag zuordnen +export async function assignToContract(req: Request, res: Response): Promise { + try { + const emailId = parseInt(req.params.id); + const { contractId } = req.body; + const userId = (req as any).userId; // Falls Auth-Middleware userId setzt + + const email = await cachedEmailService.assignEmailToContract(emailId, contractId, userId); + + res.json({ success: true, data: email } as ApiResponse); + } catch (error) { + console.error('assignToContract error:', error); + res.status(400).json({ + success: false, + error: error instanceof Error ? error.message : 'Fehler beim Zuordnen der E-Mail', + } as ApiResponse); + } +} + +// Vertragszuordnung aufheben +export async function unassignFromContract(req: Request, res: Response): Promise { + try { + const emailId = parseInt(req.params.id); + + const email = await cachedEmailService.unassignEmailFromContract(emailId); + + res.json({ success: true, data: email } as ApiResponse); + } catch (error) { + console.error('unassignFromContract error:', error); + res.status(400).json({ + success: false, + error: error instanceof Error ? error.message : 'Fehler beim Aufheben der Zuordnung', + } as ApiResponse); + } +} + +// E-Mail-Anzahl pro Ordner für ein Konto +export async function getFolderCounts(req: Request, res: Response): Promise { + try { + const stressfreiEmailId = parseInt(req.params.id); + + const counts = await cachedEmailService.getFolderCountsForAccount(stressfreiEmailId); + + res.json({ success: true, data: counts } as ApiResponse); + } catch (error) { + console.error('getFolderCounts error:', error); + res.status(500).json({ + success: false, + error: 'Fehler beim Laden der Ordner-Anzahlen', + } as ApiResponse); + } +} + +// E-Mail-Anzahl pro Ordner für einen Vertrag +export async function getContractFolderCounts(req: Request, res: Response): Promise { + try { + const contractId = parseInt(req.params.contractId); + + const counts = await cachedEmailService.getFolderCountsForContract(contractId); + + res.json({ success: true, data: counts } as ApiResponse); + } catch (error) { + console.error('getContractFolderCounts error:', error); + res.status(500).json({ + success: false, + error: 'Fehler beim Laden der Ordner-Anzahlen', + } as ApiResponse); + } +} + +// ==================== SYNC & SEND ==================== + +// E-Mails für ein Konto synchronisieren (INBOX + SENT) +export async function syncAccount(req: Request, res: Response): Promise { + try { + const stressfreiEmailId = parseInt(req.params.id); + const fullSync = req.query.full === 'true'; + + // Synchronisiert sowohl INBOX als auch SENT + const result = await cachedEmailService.syncAllFoldersForAccount(stressfreiEmailId, { fullSync }); + + if (!result.success) { + res.status(400).json({ + success: false, + error: result.error, + } as ApiResponse); + return; + } + + res.json({ + success: true, + data: { + newEmails: result.newEmails, + totalEmails: result.totalEmails, + }, + } as ApiResponse); + } catch (error) { + console.error('syncAccount error:', error); + res.status(500).json({ + success: false, + error: 'Fehler beim Synchronisieren der E-Mails', + } as ApiResponse); + } +} + +// E-Mail senden +export async function sendEmailFromAccount(req: Request, res: Response): Promise { + try { + const stressfreiEmailId = parseInt(req.params.id); + const { to, cc, subject, text, html, inReplyTo, references, attachments, contractId } = req.body; + + // StressfreiEmail laden + const stressfreiEmail = await stressfreiEmailService.getEmailWithMailboxById(stressfreiEmailId); + + if (!stressfreiEmail) { + res.status(404).json({ + success: false, + error: 'E-Mail-Konto nicht gefunden', + } as ApiResponse); + return; + } + + if (!stressfreiEmail.hasMailbox) { + res.status(400).json({ + success: false, + error: 'Dieses Konto hat keine Mailbox für den Versand', + } as ApiResponse); + return; + } + + // Passwort entschlüsseln + const password = await stressfreiEmailService.getDecryptedPassword(stressfreiEmailId); + + if (!password) { + res.status(400).json({ + success: false, + error: 'Passwort für E-Mail-Versand nicht verfügbar', + } as ApiResponse); + return; + } + + // SMTP-Einstellungen vom Provider + const settings = await getImapSmtpSettings(); + + if (!settings) { + res.status(400).json({ + success: false, + error: 'Keine SMTP-Einstellungen konfiguriert', + } as ApiResponse); + return; + } + + // SMTP-Credentials + const credentials: SmtpCredentials = { + host: settings.smtpServer, + port: settings.smtpPort, + user: stressfreiEmail.email, + password, + encryption: settings.smtpEncryption, + allowSelfSignedCerts: settings.allowSelfSignedCerts, + }; + + // E-Mail-Parameter + const emailParams: SendEmailParams = { + to, + cc, + subject, + text, + html, + inReplyTo, + references, + attachments: attachments as EmailAttachment[] | undefined, + }; + + // E-Mail senden + const result = await sendEmail(credentials, stressfreiEmail.email, emailParams); + + if (!result.success) { + res.status(400).json({ + success: false, + error: result.error, + } as ApiResponse); + return; + } + + // Gesendete E-Mail im IMAP Sent-Ordner speichern (für Attachment-Download) + let sentUid: number | undefined; + if (result.rawEmail) { + try { + // IMAP-Credentials für Sent-Ordner + const imapCredentials: ImapCredentials = { + host: settings.imapServer, + port: settings.imapPort, + user: stressfreiEmail.email, + password, + encryption: settings.imapEncryption, + allowSelfSignedCerts: settings.allowSelfSignedCerts, + }; + + const appendResult = await appendToSent(imapCredentials, { + rawEmail: result.rawEmail, + }); + + if (appendResult.success && appendResult.uid) { + sentUid = appendResult.uid; + console.log(`[SMTP] Email stored in Sent folder with UID ${sentUid}`); + } + } catch (appendError) { + // Nicht kritisch - E-Mail wurde trotzdem gesendet + console.error('Error appending to IMAP Sent folder:', appendError); + } + } + + // Gesendete E-Mail im Cache speichern + try { + // Anhangsnamen extrahieren falls vorhanden + const attachmentNames = attachments?.map((a: EmailAttachment) => a.filename) || []; + + await cachedEmailService.createSentEmail(stressfreiEmailId, { + to, + cc, + subject, + text, + html, + messageId: result.messageId || `sent-${Date.now()}@opencrm.local`, + contractId: contractId ? parseInt(contractId) : undefined, + attachmentNames: attachmentNames.length > 0 ? attachmentNames : undefined, + uid: sentUid, // UID vom IMAP Sent-Ordner für Attachment-Download + }); + } catch (saveError) { + // Fehler beim Speichern nicht kritisch - E-Mail wurde trotzdem gesendet + console.error('Error saving sent email to cache:', saveError); + } + + res.json({ + success: true, + data: { messageId: result.messageId }, + } as ApiResponse); + } catch (error) { + console.error('sendEmailFromAccount error:', error); + res.status(500).json({ + success: false, + error: 'Fehler beim Senden der E-Mail', + } as ApiResponse); + } +} + +// ==================== ATTACHMENTS ==================== + +// Anhang-Liste einer E-Mail abrufen +export async function getAttachments(req: Request, res: Response): Promise { + try { + const emailId = parseInt(req.params.emailId); + + // E-Mail aus Cache laden + const email = await cachedEmailService.getCachedEmailById(emailId); + if (!email) { + res.status(404).json({ + success: false, + error: 'E-Mail nicht gefunden', + } as ApiResponse); + return; + } + + // Anhänge aus attachmentNames parsen (JSON Array) + const attachmentNames: string[] = email.attachmentNames + ? JSON.parse(email.attachmentNames) + : []; + + res.json({ + success: true, + data: attachmentNames.map((name) => ({ filename: name })), + } as ApiResponse); + } catch (error) { + console.error('getAttachments error:', error); + res.status(500).json({ + success: false, + error: 'Fehler beim Laden der Anhänge', + } as ApiResponse); + } +} + +// Einzelnen Anhang herunterladen +export async function downloadAttachment(req: Request, res: Response): Promise { + try { + const emailId = parseInt(req.params.emailId); + const filename = decodeURIComponent(req.params.filename); + + // E-Mail aus Cache laden + const email = await cachedEmailService.getCachedEmailById(emailId); + if (!email) { + res.status(404).json({ + success: false, + error: 'E-Mail nicht gefunden', + } as ApiResponse); + return; + } + + // Für gesendete E-Mails: Prüfen ob UID vorhanden (im IMAP Sent gespeichert) + if (email.folder === 'SENT' && email.uid === 0) { + res.status(400).json({ + success: false, + error: 'Anhang nicht verfügbar - E-Mail wurde vor der IMAP-Speicherung gesendet', + } as ApiResponse); + return; + } + + // StressfreiEmail laden um Zugangsdaten zu bekommen + const stressfreiEmail = await stressfreiEmailService.getEmailWithMailboxById(email.stressfreiEmailId); + if (!stressfreiEmail || !stressfreiEmail.emailPasswordEncrypted) { + res.status(400).json({ + success: false, + error: 'Keine Mailbox-Zugangsdaten verfügbar', + } as ApiResponse); + return; + } + + // IMAP-Einstellungen laden + const settings = await getImapSmtpSettings(); + if (!settings) { + res.status(400).json({ + success: false, + error: 'Keine E-Mail-Provider-Einstellungen gefunden', + } as ApiResponse); + return; + } + + // Passwort entschlüsseln + const password = decrypt(stressfreiEmail.emailPasswordEncrypted); + + // IMAP-Credentials + const credentials: ImapCredentials = { + host: settings.imapServer, + port: settings.imapPort, + user: stressfreiEmail.email, + password, + encryption: settings.imapEncryption, + allowSelfSignedCerts: settings.allowSelfSignedCerts, + }; + + // Ordner basierend auf E-Mail-Typ bestimmen (INBOX oder Sent) + const imapFolder = email.folder === 'SENT' ? 'Sent' : 'INBOX'; + + // Anhang per IMAP abrufen + const attachment = await fetchAttachment(credentials, email.uid, filename, imapFolder); + + if (!attachment) { + res.status(404).json({ + success: false, + error: 'Anhang nicht gefunden', + } as ApiResponse); + return; + } + + // Datei senden - inline (öffnen) oder attachment (download) + const disposition = req.query.view === 'true' ? 'inline' : 'attachment'; + res.setHeader('Content-Type', attachment.contentType); + res.setHeader('Content-Disposition', `${disposition}; filename="${encodeURIComponent(attachment.filename)}"`); + res.setHeader('Content-Length', attachment.size); + res.send(attachment.content); + } catch (error) { + console.error('downloadAttachment error:', error); + res.status(500).json({ + success: false, + error: 'Fehler beim Herunterladen des Anhangs', + } as ApiResponse); + } +} + +// ==================== MAILBOX ACCOUNTS ==================== + +// Mailbox-Konten eines Kunden abrufen +export async function getMailboxAccounts(req: Request, res: Response): Promise { + try { + const customerId = parseInt(req.params.customerId); + + const accounts = await cachedEmailService.getMailboxAccountsForCustomer(customerId); + + res.json({ success: true, data: accounts } as ApiResponse); + } catch (error) { + console.error('getMailboxAccounts error:', error); + res.status(500).json({ + success: false, + error: 'Fehler beim Laden der E-Mail-Konten', + } as ApiResponse); + } +} + +// Mailbox nachträglich aktivieren +export async function enableMailbox(req: Request, res: Response): Promise { + try { + const id = parseInt(req.params.id); + + const result = await stressfreiEmailService.enableMailbox(id); + + if (!result.success) { + res.status(400).json({ + success: false, + error: result.error, + } as ApiResponse); + return; + } + + res.json({ success: true } as ApiResponse); + } catch (error) { + console.error('enableMailbox error:', error); + res.status(500).json({ + success: false, + error: 'Fehler beim Aktivieren der Mailbox', + } as ApiResponse); + } +} + +// Mailbox-Status mit Provider synchronisieren +export async function syncMailboxStatus(req: Request, res: Response): Promise { + try { + const id = parseInt(req.params.id); + + const result = await stressfreiEmailService.syncMailboxStatus(id); + + if (!result.success) { + res.status(400).json({ + success: false, + error: result.error, + } as ApiResponse); + return; + } + + res.json({ + success: true, + data: { + hasMailbox: result.hasMailbox, + wasUpdated: result.wasUpdated, + }, + } as ApiResponse); + } catch (error) { + console.error('syncMailboxStatus error:', error); + res.status(500).json({ + success: false, + error: 'Fehler beim Synchronisieren des Mailbox-Status', + } as ApiResponse); + } +} + +// E-Mail-Thread abrufen +export async function getThread(req: Request, res: Response): Promise { + try { + const id = parseInt(req.params.id); + + const thread = await cachedEmailService.getEmailThread(id); + + res.json({ success: true, data: thread } as ApiResponse); + } catch (error) { + console.error('getThread error:', error); + res.status(500).json({ + success: false, + error: 'Fehler beim Laden des E-Mail-Threads', + } as ApiResponse); + } +} + +// Mailbox-Zugangsdaten abrufen (IMAP/SMTP) +export async function getMailboxCredentials(req: Request, res: Response): Promise { + try { + const id = parseInt(req.params.id); + + // StressfreiEmail laden + const stressfreiEmail = await stressfreiEmailService.getEmailWithMailboxById(id); + + if (!stressfreiEmail) { + res.status(404).json({ + success: false, + error: 'E-Mail-Konto nicht gefunden', + } as ApiResponse); + return; + } + + if (!stressfreiEmail.hasMailbox) { + res.status(400).json({ + success: false, + error: 'Keine Mailbox für diese E-Mail-Adresse', + } as ApiResponse); + return; + } + + // Passwort entschlüsseln + const password = await stressfreiEmailService.getDecryptedPassword(id); + + if (!password) { + res.status(500).json({ + success: false, + error: 'Passwort konnte nicht entschlüsselt werden', + } as ApiResponse); + return; + } + + // IMAP/SMTP-Einstellungen laden + const settings = await getImapSmtpSettings(); + + res.json({ + success: true, + data: { + email: stressfreiEmail.email, + password, + imap: settings ? { + server: settings.imapServer, + port: settings.imapPort, + encryption: settings.imapEncryption, + } : null, + smtp: settings ? { + server: settings.smtpServer, + port: settings.smtpPort, + encryption: settings.smtpEncryption, + } : null, + }, + } as ApiResponse); + } catch (error) { + console.error('getMailboxCredentials error:', error); + res.status(500).json({ + success: false, + error: 'Fehler beim Laden der Mailbox-Zugangsdaten', + } as ApiResponse); + } +} + +// Ungelesene E-Mails zählen +export async function getUnreadCount(req: Request, res: Response): Promise { + try { + const customerId = req.query.customerId ? parseInt(req.query.customerId as string) : undefined; + const contractId = req.query.contractId ? parseInt(req.query.contractId as string) : undefined; + + let count = 0; + + if (customerId) { + count = await cachedEmailService.getUnreadCountForCustomer(customerId); + } else if (contractId) { + count = await cachedEmailService.getUnreadCountForContract(contractId); + } + + res.json({ success: true, data: { count } } as ApiResponse); + } catch (error) { + console.error('getUnreadCount error:', error); + res.status(500).json({ + success: false, + error: 'Fehler beim Zählen der ungelesenen E-Mails', + } as ApiResponse); + } +} + +// E-Mail in Papierkorb verschieben (nur Admin) +export async function deleteEmail(req: Request, res: Response): Promise { + try { + const id = parseInt(req.params.id); + + // Prüfen ob E-Mail existiert + const email = await cachedEmailService.getCachedEmailById(id); + if (!email) { + res.status(404).json({ + success: false, + error: 'E-Mail nicht gefunden', + } as ApiResponse); + return; + } + + const result = await cachedEmailService.moveEmailToTrash(id); + + if (!result.success) { + res.status(400).json({ + success: false, + error: result.error, + } as ApiResponse); + return; + } + + res.json({ success: true, message: 'E-Mail in Papierkorb verschoben' } as ApiResponse); + } catch (error) { + console.error('deleteEmail error:', error); + res.status(500).json({ + success: false, + error: 'Fehler beim Löschen der E-Mail', + } as ApiResponse); + } +} + +// ==================== TRASH OPERATIONS ==================== + +// Papierkorb-E-Mails für einen Kunden abrufen +export async function getTrashEmails(req: Request, res: Response): Promise { + try { + const customerId = parseInt(req.params.customerId); + + const emails = await cachedEmailService.getTrashEmails(customerId); + + res.json({ success: true, data: emails } as ApiResponse); + } catch (error) { + console.error('getTrashEmails error:', error); + res.status(500).json({ + success: false, + error: 'Fehler beim Laden der Papierkorb-E-Mails', + } as ApiResponse); + } +} + +// Papierkorb-Anzahl für einen Kunden +export async function getTrashCount(req: Request, res: Response): Promise { + try { + const customerId = parseInt(req.params.customerId); + + const count = await cachedEmailService.getTrashCount(customerId); + + res.json({ success: true, data: { count } } as ApiResponse); + } catch (error) { + console.error('getTrashCount error:', error); + res.status(500).json({ + success: false, + error: 'Fehler beim Zählen der Papierkorb-E-Mails', + } as ApiResponse); + } +} + +// E-Mail aus Papierkorb wiederherstellen +export async function restoreEmail(req: Request, res: Response): Promise { + try { + const id = parseInt(req.params.id); + + const result = await cachedEmailService.restoreEmailFromTrash(id); + + if (!result.success) { + res.status(400).json({ + success: false, + error: result.error, + } as ApiResponse); + return; + } + + res.json({ success: true, message: 'E-Mail wiederhergestellt' } as ApiResponse); + } catch (error) { + console.error('restoreEmail error:', error); + res.status(500).json({ + success: false, + error: 'Fehler beim Wiederherstellen der E-Mail', + } as ApiResponse); + } +} + +// E-Mail endgültig löschen (aus Papierkorb) +export async function permanentDeleteEmail(req: Request, res: Response): Promise { + try { + const id = parseInt(req.params.id); + + const result = await cachedEmailService.permanentDeleteEmail(id); + + if (!result.success) { + res.status(400).json({ + success: false, + error: result.error, + } as ApiResponse); + return; + } + + res.json({ success: true, message: 'E-Mail endgültig gelöscht' } as ApiResponse); + } catch (error) { + console.error('permanentDeleteEmail error:', error); + res.status(500).json({ + success: false, + error: 'Fehler beim endgültigen Löschen der E-Mail', + } as ApiResponse); + } +} diff --git a/backend/src/controllers/stressfreiEmail.controller.ts b/backend/src/controllers/stressfreiEmail.controller.ts index 5fa1c2b7..7b20cd28 100644 --- a/backend/src/controllers/stressfreiEmail.controller.ts +++ b/backend/src/controllers/stressfreiEmail.controller.ts @@ -74,3 +74,26 @@ export async function deleteEmail(req: Request, res: Response): Promise { } as ApiResponse); } } + +export async function resetPassword(req: Request, res: Response): Promise { + try { + const result = await stressfreiEmailService.resetMailboxPassword(parseInt(req.params.id)); + if (!result.success) { + res.status(400).json({ + success: false, + error: result.error, + } as ApiResponse); + return; + } + res.json({ + success: true, + data: { password: result.password }, + message: 'Passwort wurde zurückgesetzt', + } as ApiResponse); + } catch (error) { + res.status(500).json({ + success: false, + error: error instanceof Error ? error.message : 'Fehler beim Zurücksetzen des Passworts', + } as ApiResponse); + } +} diff --git a/backend/src/index.ts b/backend/src/index.ts index fe3e99ed..cbb8583a 100644 --- a/backend/src/index.ts +++ b/backend/src/index.ts @@ -23,6 +23,7 @@ import contractCategoryRoutes from './routes/contractCategory.routes.js'; import contractTaskRoutes from './routes/contractTask.routes.js'; import appSettingRoutes from './routes/appSetting.routes.js'; import emailProviderRoutes from './routes/emailProvider.routes.js'; +import cachedEmailRoutes from './routes/cachedEmail.routes.js'; dotenv.config(); @@ -57,6 +58,7 @@ app.use('/api/contract-categories', contractCategoryRoutes); app.use('/api', contractTaskRoutes); app.use('/api/settings', appSettingRoutes); app.use('/api/email-providers', emailProviderRoutes); +app.use('/api', cachedEmailRoutes); // Health check app.get('/api/health', (req, res) => { diff --git a/backend/src/middleware/auth.ts b/backend/src/middleware/auth.ts index 4c2d92c8..b94749f2 100644 --- a/backend/src/middleware/auth.ts +++ b/backend/src/middleware/auth.ts @@ -1,26 +1,64 @@ import { Response, NextFunction } from 'express'; import jwt from 'jsonwebtoken'; +import { PrismaClient } from '@prisma/client'; import { AuthRequest, JwtPayload } from '../types/index.js'; -export function authenticate( +const prisma = new PrismaClient(); + +export async function authenticate( req: AuthRequest, res: Response, next: NextFunction -): void { +): Promise { const authHeader = req.headers.authorization; - if (!authHeader || !authHeader.startsWith('Bearer ')) { + // Token aus Header oder Query-Parameter (für Downloads) + let token: string | null = null; + + if (authHeader && authHeader.startsWith('Bearer ')) { + token = authHeader.split(' ')[1]; + } else if (req.query.token && typeof req.query.token === 'string') { + // Fallback für Downloads: Token als Query-Parameter + token = req.query.token; + } + + if (!token) { res.status(401).json({ success: false, error: 'Nicht authentifiziert' }); return; } - const token = authHeader.split(' ')[1]; - try { const decoded = jwt.verify( token, process.env.JWT_SECRET || 'fallback-secret' ) as JwtPayload; + + // Prüfen ob Token durch Rechteänderung invalidiert wurde (nur für Mitarbeiter) + if (decoded.userId && decoded.iat) { + const user = await prisma.user.findUnique({ + where: { id: decoded.userId }, + select: { tokenInvalidatedAt: true, isActive: true }, + }); + + // Benutzer nicht gefunden oder deaktiviert + if (!user || !user.isActive) { + res.status(401).json({ success: false, error: 'Benutzer nicht mehr aktiv' }); + return; + } + + // Token wurde vor der Invalidierung ausgestellt + if (user.tokenInvalidatedAt) { + const tokenIssuedAt = decoded.iat * 1000; // iat ist in Sekunden, Date ist in Millisekunden + if (tokenIssuedAt < user.tokenInvalidatedAt.getTime()) { + res.status(401).json({ + success: false, + error: 'Ihre Berechtigungen wurden geändert. Bitte melden Sie sich erneut an.', + }); + return; + } + } + } + req.user = decoded; next(); } catch { diff --git a/backend/src/routes/appSetting.routes.ts b/backend/src/routes/appSetting.routes.ts index 58680f5f..a525fcd5 100644 --- a/backend/src/routes/appSetting.routes.ts +++ b/backend/src/routes/appSetting.routes.ts @@ -1,7 +1,22 @@ import { Router } from 'express'; +import multer from 'multer'; import * as appSettingController from '../controllers/appSetting.controller.js'; +import * as backupController from '../controllers/backup.controller.js'; import { authenticate, requirePermission } from '../middleware/auth.js'; +// Multer für Backup-Upload (in Memory speichern) +const backupUpload = multer({ + storage: multer.memoryStorage(), + limits: { fileSize: 500 * 1024 * 1024 }, // 500MB max + fileFilter: (req, file, cb) => { + if (file.mimetype === 'application/zip' || file.originalname.endsWith('.zip')) { + cb(null, true); + } else { + cb(new Error('Nur ZIP-Dateien sind erlaubt')); + } + }, +}); + const router = Router(); // Öffentliche Einstellungen (für alle authentifizierten Benutzer, inkl. Kunden) @@ -26,4 +41,63 @@ router.put( appSettingController.updateSettings ); +// ==================== BACKUP & RESTORE ==================== + +// Liste aller Backups +router.get( + '/backups', + authenticate, + requirePermission('settings:update'), + backupController.listBackups +); + +// Neues Backup erstellen +router.post( + '/backup', + authenticate, + requirePermission('settings:update'), + backupController.createBackup +); + +// Backup wiederherstellen +router.post( + '/backup/:name/restore', + authenticate, + requirePermission('settings:update'), + backupController.restoreBackup +); + +// Backup löschen +router.delete( + '/backup/:name', + authenticate, + requirePermission('settings:update'), + backupController.deleteBackup +); + +// Backup als ZIP herunterladen +router.get( + '/backup/:name/download', + authenticate, + requirePermission('settings:update'), + backupController.downloadBackup +); + +// Backup-ZIP hochladen +router.post( + '/backup/upload', + authenticate, + requirePermission('settings:update'), + backupUpload.single('backup'), + backupController.uploadBackup +); + +// Werkseinstellungen (alles löschen) +router.post( + '/factory-reset', + authenticate, + requirePermission('settings:update'), + backupController.factoryReset +); + export default router; diff --git a/backend/src/routes/cachedEmail.routes.ts b/backend/src/routes/cachedEmail.routes.ts new file mode 100644 index 00000000..715d2b13 --- /dev/null +++ b/backend/src/routes/cachedEmail.routes.ts @@ -0,0 +1,237 @@ +// ==================== CACHED EMAIL ROUTES ==================== + +import { Router } from 'express'; +import * as cachedEmailController from '../controllers/cachedEmail.controller.js'; +import { authenticate, requirePermission } from '../middleware/auth.js'; + +const router = Router(); + +// ==================== E-MAIL LISTEN ==================== + +// E-Mails für Kunden (mit optionalem Account-Filter) +// GET /api/customers/:customerId/emails?accountId=1&limit=50&offset=0 +router.get( + '/customers/:customerId/emails', + authenticate, + requirePermission('customers:read'), + cachedEmailController.getEmailsForCustomer +); + +// E-Mails für Vertrag +// GET /api/contracts/:contractId/emails?limit=50&offset=0 +router.get( + '/contracts/:contractId/emails', + authenticate, + requirePermission('contracts:read'), + cachedEmailController.getEmailsForContract +); + +// Ordner-Anzahlen für Vertrag (zugeordnete E-Mails) +// GET /api/contracts/:contractId/emails/folder-counts +router.get( + '/contracts/:contractId/emails/folder-counts', + authenticate, + requirePermission('contracts:read'), + cachedEmailController.getContractFolderCounts +); + +// Mailbox-Konten eines Kunden (für Dropdown) +// GET /api/customers/:customerId/mailbox-accounts +router.get( + '/customers/:customerId/mailbox-accounts', + authenticate, + requirePermission('customers:read'), + cachedEmailController.getMailboxAccounts +); + +// Ungelesene E-Mails zählen +// GET /api/emails/unread-count?customerId=1 oder ?contractId=1 +router.get( + '/emails/unread-count', + authenticate, + requirePermission('customers:read'), + cachedEmailController.getUnreadCount +); + +// ==================== EINZELNE E-MAIL ==================== + +// Einzelne E-Mail abrufen (mit Body, markiert als gelesen) +// GET /api/emails/:id +router.get( + '/emails/:id', + authenticate, + requirePermission('customers:read'), + cachedEmailController.getEmail +); + +// E-Mail in Papierkorb verschieben (nur User mit emails:delete Permission) +// DELETE /api/emails/:id +router.delete( + '/emails/:id', + authenticate, + requirePermission('emails:delete'), + cachedEmailController.deleteEmail +); + +// ==================== PAPIERKORB ==================== + +// Papierkorb-E-Mails für Kunden abrufen +// GET /api/customers/:customerId/emails/trash +router.get( + '/customers/:customerId/emails/trash', + authenticate, + requirePermission('emails:delete'), + cachedEmailController.getTrashEmails +); + +// Papierkorb-Anzahl für Kunden +// GET /api/customers/:customerId/emails/trash/count +router.get( + '/customers/:customerId/emails/trash/count', + authenticate, + requirePermission('emails:delete'), + cachedEmailController.getTrashCount +); + +// E-Mail aus Papierkorb wiederherstellen +// POST /api/emails/:id/restore +router.post( + '/emails/:id/restore', + authenticate, + requirePermission('emails:delete'), + cachedEmailController.restoreEmail +); + +// E-Mail endgültig löschen (nur aus Papierkorb) +// DELETE /api/emails/:id/permanent +router.delete( + '/emails/:id/permanent', + authenticate, + requirePermission('emails:delete'), + cachedEmailController.permanentDeleteEmail +); + +// E-Mail-Thread abrufen +// GET /api/emails/:id/thread +router.get( + '/emails/:id/thread', + authenticate, + requirePermission('customers:read'), + cachedEmailController.getThread +); + +// Als gelesen/ungelesen markieren +// PATCH /api/emails/:id/read +router.patch( + '/emails/:id/read', + authenticate, + requirePermission('customers:update'), + cachedEmailController.markAsRead +); + +// Stern umschalten +// POST /api/emails/:id/star +router.post( + '/emails/:id/star', + authenticate, + requirePermission('customers:update'), + cachedEmailController.toggleStar +); + +// ==================== ANHÄNGE ==================== + +// Anhang-Liste einer E-Mail +// GET /api/emails/:emailId/attachments +router.get( + '/emails/:emailId/attachments', + authenticate, + requirePermission('customers:read'), + cachedEmailController.getAttachments +); + +// Einzelnen Anhang herunterladen +// GET /api/emails/:emailId/attachments/:filename +router.get( + '/emails/:emailId/attachments/:filename', + authenticate, + requirePermission('customers:read'), + cachedEmailController.downloadAttachment +); + +// ==================== VERTRAGSZUORDNUNG ==================== + +// E-Mail Vertrag zuordnen +// POST /api/emails/:id/assign { contractId: number } +router.post( + '/emails/:id/assign', + authenticate, + requirePermission('contracts:update'), + cachedEmailController.assignToContract +); + +// Zuordnung aufheben +// DELETE /api/emails/:id/assign +router.delete( + '/emails/:id/assign', + authenticate, + requirePermission('contracts:update'), + cachedEmailController.unassignFromContract +); + +// ==================== STRESSFREI-EMAIL OPERATIONEN ==================== + +// E-Mails für ein Konto synchronisieren +// POST /api/stressfrei-emails/:id/sync?full=true +router.post( + '/stressfrei-emails/:id/sync', + authenticate, + requirePermission('customers:update'), + cachedEmailController.syncAccount +); + +// E-Mail senden +// POST /api/stressfrei-emails/:id/send { to, cc, subject, text, html, inReplyTo, references } +router.post( + '/stressfrei-emails/:id/send', + authenticate, + requirePermission('customers:update'), + cachedEmailController.sendEmailFromAccount +); + +// Mailbox nachträglich aktivieren +// POST /api/stressfrei-emails/:id/enable-mailbox +router.post( + '/stressfrei-emails/:id/enable-mailbox', + authenticate, + requirePermission('customers:update'), + cachedEmailController.enableMailbox +); + +// Mailbox-Status mit Provider synchronisieren +// POST /api/stressfrei-emails/:id/sync-mailbox-status +router.post( + '/stressfrei-emails/:id/sync-mailbox-status', + authenticate, + requirePermission('customers:read'), + cachedEmailController.syncMailboxStatus +); + +// Mailbox-Zugangsdaten abrufen (IMAP/SMTP) +// GET /api/stressfrei-emails/:id/credentials +router.get( + '/stressfrei-emails/:id/credentials', + authenticate, + requirePermission('customers:read'), + cachedEmailController.getMailboxCredentials +); + +// Ordner-Anzahlen für ein Konto (INBOX, SENT, ungelesen) +// GET /api/stressfrei-emails/:id/folder-counts +router.get( + '/stressfrei-emails/:id/folder-counts', + authenticate, + requirePermission('customers:read'), + cachedEmailController.getFolderCounts +); + +export default router; diff --git a/backend/src/routes/contractCategory.routes.ts b/backend/src/routes/contractCategory.routes.ts index 070b537e..e56d8dbd 100644 --- a/backend/src/routes/contractCategory.routes.ts +++ b/backend/src/routes/contractCategory.routes.ts @@ -4,10 +4,13 @@ import { authenticate, requirePermission } from '../middleware/auth.js'; const router = Router(); +// Lesen für alle authentifizierten Benutzer router.get('/', authenticate, contractCategoryController.getContractCategories); -router.post('/', authenticate, requirePermission('platforms:create'), contractCategoryController.createContractCategory); router.get('/:id', authenticate, contractCategoryController.getContractCategory); -router.put('/:id', authenticate, requirePermission('platforms:update'), contractCategoryController.updateContractCategory); -router.delete('/:id', authenticate, requirePermission('platforms:delete'), contractCategoryController.deleteContractCategory); + +// Ändern/Löschen nur mit Entwickler-Berechtigung (Vertragstypen erfordern Formular-Anpassungen) +router.post('/', authenticate, requirePermission('developer:access'), contractCategoryController.createContractCategory); +router.put('/:id', authenticate, requirePermission('developer:access'), contractCategoryController.updateContractCategory); +router.delete('/:id', authenticate, requirePermission('developer:access'), contractCategoryController.deleteContractCategory); export default router; diff --git a/backend/src/routes/stressfreiEmail.routes.ts b/backend/src/routes/stressfreiEmail.routes.ts index 5e58ae42..c0e39670 100644 --- a/backend/src/routes/stressfreiEmail.routes.ts +++ b/backend/src/routes/stressfreiEmail.routes.ts @@ -9,4 +9,7 @@ router.get('/:id', authenticate, requirePermission('customers:read'), stressfrei router.put('/:id', authenticate, requirePermission('customers:update'), stressfreiEmailController.updateEmail); router.delete('/:id', authenticate, requirePermission('customers:delete'), stressfreiEmailController.deleteEmail); +// Passwort zurücksetzen (generiert neues Passwort und setzt es beim Provider) +router.post('/:id/reset-password', authenticate, requirePermission('customers:update'), stressfreiEmailController.resetPassword); + export default router; diff --git a/backend/src/services/backup.service.ts b/backend/src/services/backup.service.ts new file mode 100644 index 00000000..121598f4 --- /dev/null +++ b/backend/src/services/backup.service.ts @@ -0,0 +1,1186 @@ +/** + * Datenbank Backup Service + * + * Ermöglicht Backup und Restore der Datenbank und Uploads über die Web-Oberfläche. + */ + +import { PrismaClient } from '@prisma/client'; +import * as fs from 'fs'; +import * as path from 'path'; +import archiver from 'archiver'; +import AdmZip from 'adm-zip'; +import bcrypt from 'bcryptjs'; + +const prisma = new PrismaClient(); + +// Verzeichnisse +const BACKUPS_DIR = path.join(__dirname, '../../prisma/backups'); +const UPLOADS_DIR = path.join(process.cwd(), 'uploads'); + +// Stelle sicher, dass das Backup-Verzeichnis existiert +if (!fs.existsSync(BACKUPS_DIR)) { + fs.mkdirSync(BACKUPS_DIR, { recursive: true }); +} + +export interface BackupInfo { + name: string; + timestamp: string; + totalRecords: number; + tables: { table: string; count: number }[]; + sizeBytes: number; + hasUploads: boolean; + uploadSizeBytes: number; +} + +export interface BackupResult { + success: boolean; + backupName?: string; + error?: string; +} + +export interface RestoreResult { + success: boolean; + restoredRecords?: number; + restoredFiles?: number; + error?: string; +} + +// Hilfsfunktion: Datum-Strings zu Date-Objekten konvertieren +function convertDates(obj: any): any { + if (obj === null || obj === undefined) return obj; + if (typeof obj === 'string') { + if (/^\d{4}-\d{2}-\d{2}T\d{2}:\d{2}:\d{2}/.test(obj)) { + return new Date(obj); + } + return obj; + } + if (Array.isArray(obj)) { + return obj.map(convertDates); + } + if (typeof obj === 'object') { + const result: any = {}; + for (const [key, value] of Object.entries(obj)) { + result[key] = convertDates(value); + } + return result; + } + return obj; +} + +// Hilfsfunktion: JSON-Datei lesen +function readJsonFile(filePath: string): T[] { + if (!fs.existsSync(filePath)) { + return []; + } + const content = fs.readFileSync(filePath, 'utf-8'); + return JSON.parse(content); +} + +// Hilfsfunktion: Ordnergröße berechnen (rekursiv) +function getDirectorySize(dirPath: string): number { + if (!fs.existsSync(dirPath)) return 0; + + let size = 0; + const items = fs.readdirSync(dirPath); + + for (const item of items) { + const itemPath = path.join(dirPath, item); + const stats = fs.statSync(itemPath); + + if (stats.isFile()) { + size += stats.size; + } else if (stats.isDirectory()) { + size += getDirectorySize(itemPath); + } + } + + return size; +} + +// Hilfsfunktion: Ordner rekursiv kopieren +function copyDirectory(src: string, dest: string): number { + if (!fs.existsSync(src)) return 0; + + let fileCount = 0; + fs.mkdirSync(dest, { recursive: true }); + + const items = fs.readdirSync(src); + for (const item of items) { + const srcPath = path.join(src, item); + const destPath = path.join(dest, item); + const stats = fs.statSync(srcPath); + + if (stats.isDirectory()) { + fileCount += copyDirectory(srcPath, destPath); + } else { + fs.copyFileSync(srcPath, destPath); + fileCount++; + } + } + + return fileCount; +} + +// Hilfsfunktion: Ordner rekursiv löschen +function deleteDirectory(dirPath: string): void { + if (!fs.existsSync(dirPath)) return; + + const items = fs.readdirSync(dirPath); + for (const item of items) { + const itemPath = path.join(dirPath, item); + const stats = fs.statSync(itemPath); + + if (stats.isDirectory()) { + deleteDirectory(itemPath); + } else { + fs.unlinkSync(itemPath); + } + } + + fs.rmdirSync(dirPath); +} + +/** + * Liste aller verfügbaren Backups + */ +export async function listBackups(): Promise { + const backups: BackupInfo[] = []; + + if (!fs.existsSync(BACKUPS_DIR)) { + return backups; + } + + const dirs = fs.readdirSync(BACKUPS_DIR) + .filter(f => { + const fullPath = path.join(BACKUPS_DIR, f); + return fs.statSync(fullPath).isDirectory() && f !== '.gitkeep' && !f.startsWith('.'); + }) + .sort() + .reverse(); + + for (const dir of dirs) { + const backupDir = path.join(BACKUPS_DIR, dir); + const infoPath = path.join(backupDir, '_backup-info.json'); + const uploadsPath = path.join(backupDir, 'uploads'); + + if (fs.existsSync(infoPath)) { + try { + const info = JSON.parse(fs.readFileSync(infoPath, 'utf-8')); + const hasUploads = fs.existsSync(uploadsPath); + const uploadSize = hasUploads ? getDirectorySize(uploadsPath) : 0; + + backups.push({ + name: dir, + timestamp: info.timestamp, + totalRecords: info.totalRecords, + tables: info.tables, + sizeBytes: getDirectorySize(backupDir), + hasUploads, + uploadSizeBytes: uploadSize, + }); + } catch { + backups.push({ + name: dir, + timestamp: dir, + totalRecords: 0, + tables: [], + sizeBytes: getDirectorySize(backupDir), + hasUploads: fs.existsSync(uploadsPath), + uploadSizeBytes: 0, + }); + } + } + } + + return backups; +} + +/** + * Neues Backup erstellen (inkl. Uploads) + */ +export async function createBackup(): Promise { + try { + const timestamp = new Date().toISOString().replace(/[:.]/g, '-').slice(0, 19); + const backupDir = path.join(BACKUPS_DIR, timestamp); + + fs.mkdirSync(backupDir, { recursive: true }); + + // Tabellen in Abhängigkeitsreihenfolge + const tables = [ + { name: 'Permission', query: () => prisma.permission.findMany() }, + { name: 'Role', query: () => prisma.role.findMany() }, + { name: 'SalesPlatform', query: () => prisma.salesPlatform.findMany() }, + { name: 'ContractCategory', query: () => prisma.contractCategory.findMany() }, + { name: 'CancellationPeriod', query: () => prisma.cancellationPeriod.findMany() }, + { name: 'ContractDuration', query: () => prisma.contractDuration.findMany() }, + { name: 'AppSetting', query: () => prisma.appSetting.findMany() }, + { name: 'EmailProviderConfig', query: () => prisma.emailProviderConfig.findMany() }, + { name: 'Provider', query: () => prisma.provider.findMany() }, + { name: 'RolePermission', query: () => prisma.rolePermission.findMany() }, + { name: 'User', query: () => prisma.user.findMany() }, + { name: 'Customer', query: () => prisma.customer.findMany() }, + { name: 'Tariff', query: () => prisma.tariff.findMany() }, + { name: 'UserRole', query: () => prisma.userRole.findMany() }, + { name: 'CustomerRepresentative', query: () => prisma.customerRepresentative.findMany() }, + { name: 'StressfreiEmail', query: () => prisma.stressfreiEmail.findMany() }, + { name: 'Contract', query: () => prisma.contract.findMany() }, + { name: 'Meter', query: () => prisma.meter.findMany() }, + { name: 'CachedEmail', query: () => prisma.cachedEmail.findMany() }, + { name: 'ContractTask', query: () => prisma.contractTask.findMany() }, + { name: 'MeterReading', query: () => prisma.meterReading.findMany() }, + { name: 'ContractTaskSubtask', query: () => prisma.contractTaskSubtask.findMany() }, + { name: 'EnergyContractDetails', query: () => prisma.energyContractDetails.findMany() }, + { name: 'InternetContractDetails', query: () => prisma.internetContractDetails.findMany() }, + { name: 'MobileContractDetails', query: () => prisma.mobileContractDetails.findMany() }, + { name: 'TvContractDetails', query: () => prisma.tvContractDetails.findMany() }, + { name: 'CarInsuranceDetails', query: () => prisma.carInsuranceDetails.findMany() }, + { name: 'PhoneNumber', query: () => prisma.phoneNumber.findMany() }, + { name: 'SimCard', query: () => prisma.simCard.findMany() }, + { name: 'Address', query: () => prisma.address.findMany() }, + { name: 'BankCard', query: () => prisma.bankCard.findMany() }, + { name: 'IdentityDocument', query: () => prisma.identityDocument.findMany() }, + ]; + + let totalRecords = 0; + const stats: { table: string; count: number }[] = []; + + for (const table of tables) { + try { + const data = await table.query(); + const count = data.length; + totalRecords += count; + stats.push({ table: table.name, count }); + + const filePath = path.join(backupDir, `${table.name}.json`); + fs.writeFileSync(filePath, JSON.stringify(data, null, 2)); + } catch { + stats.push({ table: table.name, count: 0 }); + } + } + + // Uploads-Ordner kopieren (falls vorhanden) + let uploadFileCount = 0; + if (fs.existsSync(UPLOADS_DIR)) { + const uploadsBackupDir = path.join(backupDir, 'uploads'); + uploadFileCount = copyDirectory(UPLOADS_DIR, uploadsBackupDir); + } + + // Backup-Info speichern + const backupInfo = { + timestamp: new Date().toISOString(), + totalRecords, + tables: stats, + uploadFiles: uploadFileCount, + }; + fs.writeFileSync(path.join(backupDir, '_backup-info.json'), JSON.stringify(backupInfo, null, 2)); + + return { success: true, backupName: timestamp }; + } catch (error: any) { + return { success: false, error: error.message }; + } +} + +/** + * Backup wiederherstellen (inkl. Uploads) + */ +export async function restoreBackup(backupName: string): Promise { + const backupDir = path.join(BACKUPS_DIR, backupName); + + if (!fs.existsSync(backupDir)) { + return { success: false, error: 'Backup nicht gefunden' }; + } + + try { + // Foreign Key Checks deaktivieren + await prisma.$executeRawUnsafe('SET FOREIGN_KEY_CHECKS = 0'); + + // WICHTIG: Alle Tabellen vor dem Restore leeren, damit keine alten Daten übrig bleiben + console.log('[Restore] Lösche alle bestehenden Daten...'); + + // Detail-Tabellen + await prisma.carInsuranceDetails.deleteMany({}); + await prisma.tvContractDetails.deleteMany({}); + await prisma.simCard.deleteMany({}); + await prisma.mobileContractDetails.deleteMany({}); + await prisma.phoneNumber.deleteMany({}); + await prisma.internetContractDetails.deleteMany({}); + await prisma.energyContractDetails.deleteMany({}); + await prisma.meterReading.deleteMany({}); + + // E-Mail & Verträge + await prisma.cachedEmail.deleteMany({}); + await prisma.contractTaskSubtask.deleteMany({}); + await prisma.contractTask.deleteMany({}); + await prisma.contract.deleteMany({}); + + // Kunden-bezogene Daten + await prisma.stressfreiEmail.deleteMany({}); + await prisma.meter.deleteMany({}); + await prisma.identityDocument.deleteMany({}); + await prisma.bankCard.deleteMany({}); + await prisma.address.deleteMany({}); + await prisma.customerRepresentative.deleteMany({}); + + // Benutzer & Rollen + await prisma.userRole.deleteMany({}); + await prisma.user.deleteMany({}); + await prisma.customer.deleteMany({}); + + // Stammdaten + await prisma.tariff.deleteMany({}); + await prisma.provider.deleteMany({}); + await prisma.rolePermission.deleteMany({}); + await prisma.role.deleteMany({}); + await prisma.permission.deleteMany({}); + await prisma.salesPlatform.deleteMany({}); + await prisma.cancellationPeriod.deleteMany({}); + await prisma.contractDuration.deleteMany({}); + await prisma.contractCategory.deleteMany({}); + await prisma.emailProviderConfig.deleteMany({}); + await prisma.appSetting.deleteMany({}); + + console.log('[Restore] Alle Daten gelöscht, starte Wiederherstellung...'); + + // Restore-Reihenfolge + const restoreOrder = [ + { + name: 'Permission', + restore: async (data: any[]) => { + for (const item of data) { + await prisma.permission.upsert({ + where: { id: item.id }, + update: convertDates(item), + create: convertDates(item), + }); + } + }, + }, + { + name: 'Role', + restore: async (data: any[]) => { + for (const item of data) { + await prisma.role.upsert({ + where: { id: item.id }, + update: convertDates(item), + create: convertDates(item), + }); + } + }, + }, + { + name: 'SalesPlatform', + restore: async (data: any[]) => { + for (const item of data) { + await prisma.salesPlatform.upsert({ + where: { id: item.id }, + update: convertDates(item), + create: convertDates(item), + }); + } + }, + }, + { + name: 'ContractCategory', + restore: async (data: any[]) => { + for (const item of data) { + await prisma.contractCategory.upsert({ + where: { id: item.id }, + update: convertDates(item), + create: convertDates(item), + }); + } + }, + }, + { + name: 'CancellationPeriod', + restore: async (data: any[]) => { + for (const item of data) { + await prisma.cancellationPeriod.upsert({ + where: { id: item.id }, + update: convertDates(item), + create: convertDates(item), + }); + } + }, + }, + { + name: 'ContractDuration', + restore: async (data: any[]) => { + for (const item of data) { + await prisma.contractDuration.upsert({ + where: { id: item.id }, + update: convertDates(item), + create: convertDates(item), + }); + } + }, + }, + { + name: 'AppSetting', + restore: async (data: any[]) => { + for (const item of data) { + await prisma.appSetting.upsert({ + where: { id: item.id }, + update: convertDates(item), + create: convertDates(item), + }); + } + }, + }, + { + name: 'EmailProviderConfig', + restore: async (data: any[]) => { + for (const item of data) { + await prisma.emailProviderConfig.upsert({ + where: { id: item.id }, + update: convertDates(item), + create: convertDates(item), + }); + } + }, + }, + { + name: 'Provider', + restore: async (data: any[]) => { + for (const item of data) { + await prisma.provider.upsert({ + where: { id: item.id }, + update: convertDates(item), + create: convertDates(item), + }); + } + }, + }, + { + name: 'RolePermission', + restore: async (data: any[]) => { + for (const item of data) { + await prisma.rolePermission.upsert({ + where: { roleId_permissionId: { roleId: item.roleId, permissionId: item.permissionId } }, + update: {}, + create: convertDates(item), + }); + } + }, + }, + { + name: 'User', + restore: async (data: any[]) => { + for (const item of data) { + await prisma.user.upsert({ + where: { id: item.id }, + update: convertDates(item), + create: convertDates(item), + }); + } + }, + }, + { + name: 'Customer', + restore: async (data: any[]) => { + for (const item of data) { + await prisma.customer.upsert({ + where: { id: item.id }, + update: convertDates(item), + create: convertDates(item), + }); + } + }, + }, + { + name: 'Tariff', + restore: async (data: any[]) => { + for (const item of data) { + await prisma.tariff.upsert({ + where: { id: item.id }, + update: convertDates(item), + create: convertDates(item), + }); + } + }, + }, + { + name: 'UserRole', + restore: async (data: any[]) => { + for (const item of data) { + await prisma.userRole.upsert({ + where: { userId_roleId: { userId: item.userId, roleId: item.roleId } }, + update: {}, + create: convertDates(item), + }); + } + }, + }, + { + name: 'CustomerRepresentative', + restore: async (data: any[]) => { + for (const item of data) { + await prisma.customerRepresentative.upsert({ + where: { id: item.id }, + update: convertDates(item), + create: convertDates(item), + }); + } + }, + }, + { + name: 'StressfreiEmail', + restore: async (data: any[]) => { + for (const item of data) { + await prisma.stressfreiEmail.upsert({ + where: { id: item.id }, + update: convertDates(item), + create: convertDates(item), + }); + } + }, + }, + { + name: 'Contract', + restore: async (data: any[]) => { + for (const item of data) { + await prisma.contract.upsert({ + where: { id: item.id }, + update: convertDates(item), + create: convertDates(item), + }); + } + }, + }, + { + name: 'Meter', + restore: async (data: any[]) => { + for (const item of data) { + await prisma.meter.upsert({ + where: { id: item.id }, + update: convertDates(item), + create: convertDates(item), + }); + } + }, + }, + { + name: 'CachedEmail', + restore: async (data: any[]) => { + for (const item of data) { + await prisma.cachedEmail.upsert({ + where: { id: item.id }, + update: convertDates(item), + create: convertDates(item), + }); + } + }, + }, + { + name: 'ContractTask', + restore: async (data: any[]) => { + for (const item of data) { + await prisma.contractTask.upsert({ + where: { id: item.id }, + update: convertDates(item), + create: convertDates(item), + }); + } + }, + }, + { + name: 'MeterReading', + restore: async (data: any[]) => { + for (const item of data) { + await prisma.meterReading.upsert({ + where: { id: item.id }, + update: convertDates(item), + create: convertDates(item), + }); + } + }, + }, + { + name: 'ContractTaskSubtask', + restore: async (data: any[]) => { + for (const item of data) { + await prisma.contractTaskSubtask.upsert({ + where: { id: item.id }, + update: convertDates(item), + create: convertDates(item), + }); + } + }, + }, + { + name: 'EnergyContractDetails', + restore: async (data: any[]) => { + for (const item of data) { + await prisma.energyContractDetails.upsert({ + where: { id: item.id }, + update: convertDates(item), + create: convertDates(item), + }); + } + }, + }, + { + name: 'InternetContractDetails', + restore: async (data: any[]) => { + for (const item of data) { + await prisma.internetContractDetails.upsert({ + where: { id: item.id }, + update: convertDates(item), + create: convertDates(item), + }); + } + }, + }, + { + name: 'MobileContractDetails', + restore: async (data: any[]) => { + for (const item of data) { + await prisma.mobileContractDetails.upsert({ + where: { id: item.id }, + update: convertDates(item), + create: convertDates(item), + }); + } + }, + }, + { + name: 'TvContractDetails', + restore: async (data: any[]) => { + for (const item of data) { + await prisma.tvContractDetails.upsert({ + where: { id: item.id }, + update: convertDates(item), + create: convertDates(item), + }); + } + }, + }, + { + name: 'CarInsuranceDetails', + restore: async (data: any[]) => { + for (const item of data) { + await prisma.carInsuranceDetails.upsert({ + where: { id: item.id }, + update: convertDates(item), + create: convertDates(item), + }); + } + }, + }, + { + name: 'PhoneNumber', + restore: async (data: any[]) => { + for (const item of data) { + await prisma.phoneNumber.upsert({ + where: { id: item.id }, + update: convertDates(item), + create: convertDates(item), + }); + } + }, + }, + { + name: 'SimCard', + restore: async (data: any[]) => { + for (const item of data) { + await prisma.simCard.upsert({ + where: { id: item.id }, + update: convertDates(item), + create: convertDates(item), + }); + } + }, + }, + { + name: 'Address', + restore: async (data: any[]) => { + for (const item of data) { + await prisma.address.upsert({ + where: { id: item.id }, + update: convertDates(item), + create: convertDates(item), + }); + } + }, + }, + { + name: 'BankCard', + restore: async (data: any[]) => { + for (const item of data) { + await prisma.bankCard.upsert({ + where: { id: item.id }, + update: convertDates(item), + create: convertDates(item), + }); + } + }, + }, + { + name: 'IdentityDocument', + restore: async (data: any[]) => { + for (const item of data) { + await prisma.identityDocument.upsert({ + where: { id: item.id }, + update: convertDates(item), + create: convertDates(item), + }); + } + }, + }, + ]; + + let totalRestored = 0; + + for (const table of restoreOrder) { + const filePath = path.join(backupDir, `${table.name}.json`); + const data = readJsonFile(filePath); + + if (data.length === 0) continue; + + try { + await table.restore(data); + totalRestored += data.length; + } catch { + // Fehler bei einzelner Tabelle, weitermachen + } + } + + // Foreign Key Checks wieder aktivieren + await prisma.$executeRawUnsafe('SET FOREIGN_KEY_CHECKS = 1'); + + // Uploads wiederherstellen + let restoredFiles = 0; + const uploadsBackupDir = path.join(backupDir, 'uploads'); + if (fs.existsSync(uploadsBackupDir)) { + // Bestehenden Uploads-Ordner leeren (optional: könnte auch nur überschreiben) + if (fs.existsSync(UPLOADS_DIR)) { + deleteDirectory(UPLOADS_DIR); + } + restoredFiles = copyDirectory(uploadsBackupDir, UPLOADS_DIR); + } + + return { success: true, restoredRecords: totalRestored, restoredFiles }; + } catch (error: any) { + try { + await prisma.$executeRawUnsafe('SET FOREIGN_KEY_CHECKS = 1'); + } catch {} + return { success: false, error: error.message }; + } +} + +/** + * Backup löschen + */ +export async function deleteBackup(backupName: string): Promise<{ success: boolean; error?: string }> { + const backupDir = path.join(BACKUPS_DIR, backupName); + + if (!fs.existsSync(backupDir)) { + return { success: false, error: 'Backup nicht gefunden' }; + } + + try { + deleteDirectory(backupDir); + return { success: true }; + } catch (error: any) { + return { success: false, error: error.message }; + } +} + +/** + * Backup als ZIP-Datei erstellen und Stream zurückgeben + */ +export async function createBackupZip(backupName: string): Promise<{ stream: archiver.Archiver; filename: string } | { error: string }> { + const backupDir = path.join(BACKUPS_DIR, backupName); + + if (!fs.existsSync(backupDir)) { + return { error: 'Backup nicht gefunden' }; + } + + const archive = archiver('zip', { zlib: { level: 9 } }); + + // Alle Dateien im Backup-Ordner hinzufügen + archive.directory(backupDir, false); + + return { + stream: archive, + filename: `opencrm-backup-${backupName}.zip`, + }; +} + +/** + * ZIP-Backup hochladen und extrahieren + */ +export async function uploadBackupZip(zipBuffer: Buffer): Promise { + try { + const zip = new AdmZip(zipBuffer); + const entries = zip.getEntries(); + + // Prüfen ob gültiges Backup (muss _backup-info.json enthalten) + const hasBackupInfo = entries.some(entry => entry.entryName === '_backup-info.json'); + if (!hasBackupInfo) { + return { success: false, error: 'Ungültiges Backup-Archiv: _backup-info.json fehlt' }; + } + + // Backup-Info lesen um Namen zu bestimmen + const infoEntry = entries.find(entry => entry.entryName === '_backup-info.json'); + let backupName: string; + + try { + const infoContent = infoEntry!.getData().toString('utf8'); + const info = JSON.parse(infoContent); + // Backup-Name aus Timestamp generieren + backupName = new Date(info.timestamp).toISOString().replace(/[:.]/g, '-').slice(0, 19); + } catch { + // Fallback: Aktueller Timestamp + backupName = new Date().toISOString().replace(/[:.]/g, '-').slice(0, 19) + '-uploaded'; + } + + const backupDir = path.join(BACKUPS_DIR, backupName); + + // Falls Backup mit diesem Namen existiert, Suffix hinzufügen + let finalBackupDir = backupDir; + let suffix = 1; + while (fs.existsSync(finalBackupDir)) { + finalBackupDir = `${backupDir}-${suffix}`; + suffix++; + } + + const finalBackupName = path.basename(finalBackupDir); + + // ZIP extrahieren + zip.extractAllTo(finalBackupDir, true); + + return { success: true, backupName: finalBackupName }; + } catch (error: any) { + return { success: false, error: error.message }; + } +} + +/** + * Pfad zum Backup-Verzeichnis zurückgeben + */ +export function getBackupsDir(): string { + return BACKUPS_DIR; +} + +/** + * Werkseinstellungen - Alle Daten löschen (außer Backups) + * + * Löscht alle Datenbankeinträge und Uploads, behält aber Backups. + * Erstellt einen Admin-Benutzer und notwendige Stammdaten. + */ +export async function factoryReset(): Promise<{ success: boolean; error?: string }> { + try { + // Foreign Key Checks deaktivieren + await prisma.$executeRawUnsafe('SET FOREIGN_KEY_CHECKS = 0'); + + // Tabellen in korrekter Reihenfolge leeren (abhängige zuerst) + // Detail-Tabellen + await prisma.carInsuranceDetails.deleteMany({}); + await prisma.tvContractDetails.deleteMany({}); + await prisma.simCard.deleteMany({}); + await prisma.mobileContractDetails.deleteMany({}); + await prisma.phoneNumber.deleteMany({}); + await prisma.internetContractDetails.deleteMany({}); + await prisma.energyContractDetails.deleteMany({}); + await prisma.meterReading.deleteMany({}); + + // E-Mail & Verträge + await prisma.cachedEmail.deleteMany({}); + await prisma.contractTaskSubtask.deleteMany({}); + await prisma.contractTask.deleteMany({}); + await prisma.contract.deleteMany({}); + + // Kunden-bezogene Daten + await prisma.stressfreiEmail.deleteMany({}); + await prisma.meter.deleteMany({}); + await prisma.identityDocument.deleteMany({}); + await prisma.bankCard.deleteMany({}); + await prisma.address.deleteMany({}); + await prisma.customerRepresentative.deleteMany({}); + + // Benutzer & Rollen (außer Admin) + await prisma.userRole.deleteMany({}); + await prisma.user.deleteMany({}); + await prisma.customer.deleteMany({}); + + // Stammdaten + await prisma.tariff.deleteMany({}); + await prisma.provider.deleteMany({}); + await prisma.rolePermission.deleteMany({}); + await prisma.role.deleteMany({}); + await prisma.permission.deleteMany({}); + await prisma.salesPlatform.deleteMany({}); + await prisma.cancellationPeriod.deleteMany({}); + await prisma.contractDuration.deleteMany({}); + await prisma.contractCategory.deleteMany({}); + await prisma.emailProviderConfig.deleteMany({}); + await prisma.appSetting.deleteMany({}); + + // Foreign Key Checks wieder aktivieren + await prisma.$executeRawUnsafe('SET FOREIGN_KEY_CHECKS = 1'); + + // Uploads-Verzeichnis leeren (aber nicht das Verzeichnis selbst) + if (fs.existsSync(UPLOADS_DIR)) { + const items = fs.readdirSync(UPLOADS_DIR); + for (const item of items) { + const itemPath = path.join(UPLOADS_DIR, item); + const stats = fs.statSync(itemPath); + if (stats.isDirectory()) { + deleteDirectory(itemPath); + } else { + fs.unlinkSync(itemPath); + } + } + } + + // Grundlegende Stammdaten neu anlegen (aus Seed) + // Berechtigungen - muss mit seed.ts übereinstimmen! + const resourcePermissions: Record = { + // Haupt-Ressourcen (CRUD) + customers: ['create', 'read', 'update', 'delete'], + contracts: ['create', 'read', 'update', 'delete'], + users: ['create', 'read', 'update', 'delete'], + platforms: ['create', 'read', 'update', 'delete'], + providers: ['create', 'read', 'update', 'delete'], + tariffs: ['create', 'read', 'update', 'delete'], + // Lookup-Tabellen (nur lesen) + 'contract-categories': ['read'], + 'cancellation-periods': ['read'], + 'contract-durations': ['read'], + // Einstellungen (nur lesen/ändern) + settings: ['read', 'update'], + // Spezial-Permissions + developer: ['access'], + emails: ['delete'], + }; + + for (const [resource, actions] of Object.entries(resourcePermissions)) { + for (const action of actions) { + await prisma.permission.create({ + data: { resource, action }, + }); + } + } + console.log('[FactoryReset] Berechtigungen erstellt'); + + // Admin-Rolle mit allen Berechtigungen (außer developer:access) + const allPermissions = await prisma.permission.findMany(); + const adminRole = await prisma.role.create({ + data: { + name: 'Admin', + description: 'Voller Zugriff auf alle Funktionen', + permissions: { + create: allPermissions + .filter(p => !(p.resource === 'developer' && p.action === 'access')) + .map(p => ({ permissionId: p.id })), + }, + }, + }); + + // Developer-Rolle - ALLE Berechtigungen inkl. developer:access + await prisma.role.create({ + data: { + name: 'Developer', + description: 'Voller Zugriff inkl. Entwickler-Tools', + permissions: { + create: allPermissions.map(p => ({ permissionId: p.id })), + }, + }, + }); + + // Mitarbeiter-Rolle - customers, contracts + read-only auf Stammdaten + const employeePermIds = allPermissions + .filter(p => + p.resource === 'customers' || + p.resource === 'contracts' || + (p.action === 'read' && ['platforms', 'providers', 'tariffs', 'contract-categories', 'cancellation-periods', 'contract-durations'].includes(p.resource)) + ) + .map(p => p.id); + await prisma.role.create({ + data: { + name: 'Mitarbeiter', + description: 'Kann Kunden und Verträge verwalten', + permissions: { + create: employeePermIds.map(id => ({ permissionId: id })), + }, + }, + }); + + // Nur-Lesen Rolle + const readOnlyResources = ['customers', 'contracts', 'platforms', 'providers', 'tariffs', 'contract-categories', 'cancellation-periods', 'contract-durations']; + const readOnlyPermIds = allPermissions + .filter(p => p.action === 'read' && readOnlyResources.includes(p.resource)) + .map(p => p.id); + await prisma.role.create({ + data: { + name: 'Mitarbeiter (Nur-Lesen)', + description: 'Kann nur lesen, keine Änderungen', + permissions: { + create: readOnlyPermIds.map(id => ({ permissionId: id })), + }, + }, + }); + + // Kunden-Rolle + await prisma.role.create({ + data: { + name: 'Kunde', + description: 'Kann nur eigene Daten lesen', + permissions: { + create: readOnlyPermIds.map(id => ({ permissionId: id })), + }, + }, + }); + console.log('[FactoryReset] Rollen erstellt'); + + // Standard Admin-Benutzer erstellen + console.log('[FactoryReset] Erstelle Admin-Benutzer...'); + const hashedPassword = await bcrypt.hash('admin', 10); + console.log('[FactoryReset] Passwort gehasht, Admin-Rolle ID:', adminRole.id); + + const adminUser = await prisma.user.create({ + data: { + email: 'admin@admin.com', + password: hashedPassword, + firstName: 'Admin', + lastName: 'User', + roles: { + create: [{ roleId: adminRole.id }], + }, + }, + }); + console.log('[FactoryReset] Admin-Benutzer erstellt mit ID:', adminUser.id); + + // Standard Kündigungsfristen (wie in seed.ts) + const cancellationPeriods = [ + { code: '14D', description: '14 Tage' }, + { code: '1M', description: '1 Monat' }, + { code: '2M', description: '2 Monate' }, + { code: '3M', description: '3 Monate' }, + { code: '6M', description: '6 Monate' }, + { code: '12M', description: '12 Monate' }, + { code: '1W', description: '1 Woche' }, + { code: '2W', description: '2 Wochen' }, + { code: '4W', description: '4 Wochen' }, + { code: '6W', description: '6 Wochen' }, + ]; + for (const cp of cancellationPeriods) { + await prisma.cancellationPeriod.create({ data: cp }); + } + console.log('[FactoryReset] Kündigungsfristen erstellt'); + + // Standard Vertragslaufzeiten (wie in seed.ts) + const contractDurations = [ + { code: '1M', description: '1 Monat' }, + { code: '3M', description: '3 Monate' }, + { code: '6M', description: '6 Monate' }, + { code: '12M', description: '12 Monate' }, + { code: '24M', description: '24 Monate' }, + { code: '36M', description: '36 Monate' }, + { code: '1J', description: '1 Jahr' }, + { code: '2J', description: '2 Jahre' }, + { code: '3J', description: '3 Jahre' }, + { code: '4J', description: '4 Jahre' }, + { code: '5J', description: '5 Jahre' }, + { code: 'UNBEFRISTET', description: 'Unbefristet' }, + ]; + for (const cd of contractDurations) { + await prisma.contractDuration.create({ data: cd }); + } + console.log('[FactoryReset] Vertragslaufzeiten erstellt'); + + // Standard Vertragstypen (wie in seed.ts - WICHTIG: Diese müssen mit den Formularen übereinstimmen!) + const contractCategories = [ + { code: 'ELECTRICITY', name: 'Strom', icon: 'Zap', color: '#FFC107', sortOrder: 1 }, + { code: 'GAS', name: 'Gas', icon: 'Flame', color: '#FF5722', sortOrder: 2 }, + { code: 'DSL', name: 'DSL', icon: 'Wifi', color: '#2196F3', sortOrder: 3 }, + { code: 'FIBER', name: 'Glasfaser', icon: 'Cable', color: '#9C27B0', sortOrder: 4 }, + { code: 'CABLE', name: 'Kabel Internet (Coax)', icon: 'Cable', color: '#00BCD4', sortOrder: 5 }, + { code: 'MOBILE', name: 'Mobilfunk', icon: 'Smartphone', color: '#4CAF50', sortOrder: 6 }, + { code: 'TV', name: 'TV', icon: 'Tv', color: '#E91E63', sortOrder: 7 }, + { code: 'CAR_INSURANCE', name: 'KFZ-Versicherung', icon: 'Car', color: '#607D8B', sortOrder: 8 }, + ]; + for (const cat of contractCategories) { + await prisma.contractCategory.create({ data: cat }); + } + console.log('[FactoryReset] Vertragstypen erstellt'); + + // Standard Vertriebsplattformen (wie in seed.ts) + const platforms = ['Moon Fachhandel', 'Verivox', 'Check24', 'Eigenvermittlung']; + for (const name of platforms) { + await prisma.salesPlatform.create({ data: { name, isActive: true } }); + } + console.log('[FactoryReset] Vertriebsplattformen erstellt'); + + // Standard Anbieter (wie in seed.ts) + const providers = [ + { + name: 'Vodafone', + portalUrl: 'https://www.vodafone.de/meinvodafone/account/login', + usernameFieldName: 'username', + passwordFieldName: 'password', + }, + { + name: 'Klarmobil', + portalUrl: 'https://www.klarmobil.de/login', + usernameFieldName: 'username', + passwordFieldName: 'password', + }, + { + name: 'Otelo', + portalUrl: 'https://www.otelo.de/mein-otelo/login', + usernameFieldName: 'username', + passwordFieldName: 'password', + }, + { + name: 'Congstar', + portalUrl: 'https://www.congstar.de/login/', + usernameFieldName: 'username', + passwordFieldName: 'password', + }, + { + name: 'Telekom', + portalUrl: 'https://www.telekom.de/kundencenter/startseite', + usernameFieldName: 'username', + passwordFieldName: 'password', + }, + { + name: 'O2', + portalUrl: 'https://www.o2online.de/ecare/selfcare', + usernameFieldName: 'username', + passwordFieldName: 'password', + }, + { + name: '1&1', + portalUrl: 'https://control-center.1und1.de/', + usernameFieldName: 'username', + passwordFieldName: 'password', + }, + ]; + for (const provider of providers) { + await prisma.provider.create({ data: { ...provider, isActive: true } }); + } + console.log('[FactoryReset] Anbieter erstellt'); + + // Standard App-Einstellungen (wie in seed.ts) + const appSettings = [ + { key: 'deadlineCriticalDays', value: '14' }, + { key: 'deadlineWarningDays', value: '42' }, + { key: 'deadlineOkDays', value: '90' }, + { key: 'companyName', value: 'OpenCRM' }, + { key: 'defaultEmailDomain', value: 'stressfrei-wechseln.de' }, + ]; + for (const setting of appSettings) { + await prisma.appSetting.create({ data: setting }); + } + console.log('[FactoryReset] App-Einstellungen erstellt'); + + return { success: true }; + } catch (error: any) { + try { + await prisma.$executeRawUnsafe('SET FOREIGN_KEY_CHECKS = 1'); + } catch {} + return { success: false, error: error.message }; + } +} diff --git a/backend/src/services/cachedEmail.service.ts b/backend/src/services/cachedEmail.service.ts new file mode 100644 index 00000000..a60d5b99 --- /dev/null +++ b/backend/src/services/cachedEmail.service.ts @@ -0,0 +1,957 @@ +// ==================== CACHED EMAIL SERVICE ==================== +// Service für E-Mail-Caching und Vertragszuordnung + +import { PrismaClient, CachedEmail, Prisma, EmailFolder } from '@prisma/client'; +import { decrypt } from '../utils/encryption.js'; +import { fetchEmails, ImapCredentials, FetchedEmail, moveToTrash, restoreFromTrash, permanentDelete } from './imapService.js'; +import { getImapSmtpSettings } from './emailProvider/emailProviderService.js'; + +const prisma = new PrismaClient(); + +// ==================== TYPES ==================== + +export interface CachedEmailWithRelations extends CachedEmail { + stressfreiEmail?: { + id: number; + email: string; + customerId: number; + }; + contract?: { + id: number; + contractNumber: string; + } | null; +} + +// Parameter für gesendete E-Mail +export interface SentEmailParams { + to: string[]; + cc?: string[]; + subject: string; + text?: string; + html?: string; + messageId: string; + contractId?: number; // Optional: Vertrag dem die E-Mail zugeordnet wird + attachmentNames?: string[]; // Namen der Anhänge + uid?: number; // UID im IMAP Sent-Ordner (für Attachment-Download) +} + +export interface SyncResult { + success: boolean; + newEmails: number; + totalEmails: number; + error?: string; +} + +export interface EmailListOptions { + stressfreiEmailId?: number; + customerId?: number; + contractId?: number; + folder?: string; + limit?: number; + offset?: number; + includeBody?: boolean; +} + +// ==================== SYNC FUNCTIONS ==================== + +// E-Mails für eine StressfreiEmail synchronisieren +export async function syncEmailsForAccount( + stressfreiEmailId: number, + options?: { folder?: string; fullSync?: boolean } +): Promise { + const folder = options?.folder || 'INBOX'; + const fullSync = options?.fullSync || false; + + try { + // StressfreiEmail mit Mailbox-Daten laden + const stressfreiEmail = await prisma.stressfreiEmail.findUnique({ + where: { id: stressfreiEmailId }, + }); + + if (!stressfreiEmail) { + return { success: false, newEmails: 0, totalEmails: 0, error: 'StressfreiEmail nicht gefunden' }; + } + + if (!stressfreiEmail.hasMailbox || !stressfreiEmail.emailPasswordEncrypted) { + return { success: false, newEmails: 0, totalEmails: 0, error: 'Keine Mailbox für diese E-Mail-Adresse' }; + } + + // IMAP/SMTP-Einstellungen vom Provider holen + const settings = await getImapSmtpSettings(); + if (!settings) { + return { success: false, newEmails: 0, totalEmails: 0, error: 'Keine E-Mail-Provider-Einstellungen gefunden' }; + } + + // Passwort entschlüsseln + let password: string; + try { + password = decrypt(stressfreiEmail.emailPasswordEncrypted); + } catch { + return { success: false, newEmails: 0, totalEmails: 0, error: 'Passwort konnte nicht entschlüsselt werden' }; + } + + // IMAP-Credentials zusammenstellen + const credentials: ImapCredentials = { + host: settings.imapServer, + port: settings.imapPort, + user: stressfreiEmail.email, + password, + encryption: settings.imapEncryption, + allowSelfSignedCerts: settings.allowSelfSignedCerts, + }; + + // Folder-Mapping: IMAP-Ordner zu DB-Ordner + const dbFolder = folder.toUpperCase() === 'SENT' || folder.toLowerCase() === 'sent' + ? EmailFolder.SENT + : EmailFolder.INBOX; + + // Für inkrementellen Sync: Höchste UID des Ordners ermitteln + let sinceUid: number | undefined; + if (!fullSync) { + const lastEmail = await prisma.cachedEmail.findFirst({ + where: { stressfreiEmailId, folder: dbFolder }, + orderBy: { uid: 'desc' }, + select: { uid: true }, + }); + if (lastEmail) { + sinceUid = lastEmail.uid; + } + } + + // E-Mails vom IMAP-Server abrufen + const fetchedEmails = await fetchEmails(credentials, { + folder, + sinceUid, + limit: fullSync ? 500 : 100, // Mehr bei Full-Sync + }); + + // Neue E-Mails in DB speichern + let newCount = 0; + for (const email of fetchedEmails) { + const created = await upsertCachedEmail(stressfreiEmailId, email, dbFolder); + if (created) newCount++; + } + + // Gesamtzahl ermitteln + const totalEmails = await prisma.cachedEmail.count({ + where: { stressfreiEmailId }, + }); + + return { + success: true, + newEmails: newCount, + totalEmails, + }; + } catch (error) { + console.error('syncEmailsForAccount error:', error); + const errorMessage = error instanceof Error ? error.message : 'Unbekannter Fehler'; + return { + success: false, + newEmails: 0, + totalEmails: 0, + error: errorMessage, + }; + } +} + +// Alle Ordner synchronisieren (INBOX + SENT) +export async function syncAllFoldersForAccount( + stressfreiEmailId: number, + options?: { fullSync?: boolean } +): Promise { + const fullSync = options?.fullSync || false; + + // INBOX synchronisieren + const inboxResult = await syncEmailsForAccount(stressfreiEmailId, { folder: 'INBOX', fullSync }); + + // SENT synchronisieren (Plesk verwendet "Sent" als Ordnername) + const sentResult = await syncEmailsForAccount(stressfreiEmailId, { folder: 'Sent', fullSync }); + + // Ergebnisse kombinieren + if (!inboxResult.success && !sentResult.success) { + return { + success: false, + newEmails: 0, + totalEmails: 0, + error: inboxResult.error || sentResult.error || 'Synchronisation fehlgeschlagen', + }; + } + + return { + success: true, + newEmails: inboxResult.newEmails + sentResult.newEmails, + totalEmails: inboxResult.totalEmails, + }; +} + +// Einzelne E-Mail in DB speichern/aktualisieren +async function upsertCachedEmail( + stressfreiEmailId: number, + email: FetchedEmail, + folder: EmailFolder = EmailFolder.INBOX +): Promise { + try { + // Prüfen ob bereits vorhanden (via messageId + folder) + // WICHTIG: Gleiche messageId kann in INBOX und SENT existieren (z.B. E-Mail an sich selbst) + const existing = await prisma.cachedEmail.findUnique({ + where: { + stressfreiEmailId_messageId_folder: { + stressfreiEmailId, + messageId: email.messageId, + folder, + }, + }, + }); + + if (existing) { + // Bereits vorhanden + return false; + } + + // Neue E-Mail anlegen + await prisma.cachedEmail.create({ + data: { + stressfreiEmailId, + folder, + messageId: email.messageId, + uid: email.uid, + subject: email.subject, + fromAddress: email.fromAddress, + fromName: email.fromName, + toAddresses: JSON.stringify(email.toAddresses), + ccAddresses: email.ccAddresses.length > 0 ? JSON.stringify(email.ccAddresses) : null, + receivedAt: email.date, + textBody: email.textBody, + htmlBody: email.htmlBody, + hasAttachments: email.hasAttachments, + attachmentNames: email.attachmentNames.length > 0 + ? JSON.stringify(email.attachmentNames) + : null, + isRead: folder === EmailFolder.SENT, // Gesendete E-Mails sind bereits gelesen + isStarred: false, + }, + }); + + return true; + } catch (error) { + // Duplikat-Fehler ignorieren (Race Condition) + if (error instanceof Prisma.PrismaClientKnownRequestError && error.code === 'P2002') { + return false; + } + throw error; + } +} + +// ==================== CRUD FUNCTIONS ==================== + +// E-Mails abrufen mit Optionen +export async function getCachedEmails( + options: EmailListOptions +): Promise { + const where: Prisma.CachedEmailWhereInput = { + isDeleted: false, // Gelöschte E-Mails ausschließen + }; + + if (options.stressfreiEmailId) { + where.stressfreiEmailId = options.stressfreiEmailId; + } + + if (options.customerId) { + where.stressfreiEmail = { + customerId: options.customerId, + }; + } + + if (options.contractId) { + where.contractId = options.contractId; + } + + // Folder-Filter (INBOX oder SENT) + if (options.folder === 'SENT') { + where.folder = EmailFolder.SENT; + } else if (options.folder === 'INBOX' || !options.folder) { + // Standard: Nur Posteingang + where.folder = EmailFolder.INBOX; + } + + // Body-Felder nur wenn explizit angefordert (spart Bandbreite) + const select: Prisma.CachedEmailSelect = { + id: true, + stressfreiEmailId: true, + folder: true, + messageId: true, + uid: true, + subject: true, + fromAddress: true, + fromName: true, + toAddresses: true, + ccAddresses: true, + receivedAt: true, + hasAttachments: true, + attachmentNames: true, + contractId: true, + assignedAt: true, + assignedBy: true, + isAutoAssigned: true, + isRead: true, + isStarred: true, + createdAt: true, + updatedAt: true, + stressfreiEmail: { + select: { + id: true, + email: true, + customerId: true, + }, + }, + contract: { + select: { + id: true, + contractNumber: true, + }, + }, + }; + + if (options.includeBody) { + select.textBody = true; + select.htmlBody = true; + } + + const emails = await prisma.cachedEmail.findMany({ + where, + select, + orderBy: { receivedAt: 'desc' }, + take: options.limit || 50, + skip: options.offset || 0, + }); + + return emails as CachedEmailWithRelations[]; +} + +// Einzelne E-Mail abrufen (mit Body) +export async function getCachedEmailById( + id: number +): Promise { + const email = await prisma.cachedEmail.findUnique({ + where: { id }, + include: { + stressfreiEmail: { + select: { + id: true, + email: true, + customerId: true, + }, + }, + contract: { + select: { + id: true, + contractNumber: true, + }, + }, + }, + }); + + return email as CachedEmailWithRelations | null; +} + +// E-Mail als gelesen markieren +export async function markEmailAsRead(id: number): Promise { + await prisma.cachedEmail.update({ + where: { id }, + data: { isRead: true }, + }); +} + +// E-Mail als ungelesen markieren +export async function markEmailAsUnread(id: number): Promise { + await prisma.cachedEmail.update({ + where: { id }, + data: { isRead: false }, + }); +} + +// E-Mail Stern setzen/entfernen +export async function toggleEmailStar(id: number): Promise { + const email = await prisma.cachedEmail.findUnique({ + where: { id }, + select: { isStarred: true }, + }); + + if (!email) { + throw new Error('E-Mail nicht gefunden'); + } + + const newValue = !email.isStarred; + await prisma.cachedEmail.update({ + where: { id }, + data: { isStarred: newValue }, + }); + + return newValue; +} + +// ==================== CONTRACT ASSIGNMENT ==================== + +// E-Mail einem Vertrag zuordnen +export async function assignEmailToContract( + emailId: number, + contractId: number, + userId?: number +): Promise { + // Prüfen ob E-Mail existiert + const email = await prisma.cachedEmail.findUnique({ + where: { id: emailId }, + }); + + if (!email) { + throw new Error('E-Mail nicht gefunden'); + } + + // Prüfen ob Vertrag existiert + const contract = await prisma.contract.findUnique({ + where: { id: contractId }, + }); + + if (!contract) { + throw new Error('Vertrag nicht gefunden'); + } + + // Zuordnung setzen (manuell) + const updated = await prisma.cachedEmail.update({ + where: { id: emailId }, + data: { + contractId, + assignedAt: new Date(), + assignedBy: userId || null, + isAutoAssigned: false, // Manuell zugeordnet + }, + include: { + stressfreiEmail: { + select: { + id: true, + email: true, + customerId: true, + }, + }, + contract: { + select: { + id: true, + contractNumber: true, + }, + }, + }, + }); + + return updated as CachedEmailWithRelations; +} + +// Vertragszuordnung aufheben +export async function unassignEmailFromContract( + emailId: number +): Promise { + const updated = await prisma.cachedEmail.update({ + where: { id: emailId }, + data: { + contractId: null, + assignedAt: null, + assignedBy: null, + }, + include: { + stressfreiEmail: { + select: { + id: true, + email: true, + customerId: true, + }, + }, + contract: { + select: { + id: true, + contractNumber: true, + }, + }, + }, + }); + + return updated as CachedEmailWithRelations; +} + +// ==================== HELPER FUNCTIONS ==================== + +// Anzahl ungelesener E-Mails für Kunde +export async function getUnreadCountForCustomer(customerId: number): Promise { + return prisma.cachedEmail.count({ + where: { + stressfreiEmail: { + customerId, + }, + isRead: false, + }, + }); +} + +// Anzahl ungelesener E-Mails für Vertrag +export async function getUnreadCountForContract(contractId: number): Promise { + return prisma.cachedEmail.count({ + where: { + contractId, + isRead: false, + }, + }); +} + +// E-Mail-Anzahl pro Ordner für ein Konto (total und ungelesen) +export async function getFolderCountsForAccount(stressfreiEmailId: number): Promise<{ + inbox: number; + inboxUnread: number; + sent: number; + sentUnread: number; + trash: number; + trashUnread: number; +}> { + const [inbox, inboxUnread, sent, sentUnread, trash, trashUnread] = await Promise.all([ + // INBOX total + prisma.cachedEmail.count({ + where: { stressfreiEmailId, folder: EmailFolder.INBOX, isDeleted: false }, + }), + // INBOX unread + prisma.cachedEmail.count({ + where: { stressfreiEmailId, folder: EmailFolder.INBOX, isDeleted: false, isRead: false }, + }), + // SENT total + prisma.cachedEmail.count({ + where: { stressfreiEmailId, folder: EmailFolder.SENT, isDeleted: false }, + }), + // SENT unread + prisma.cachedEmail.count({ + where: { stressfreiEmailId, folder: EmailFolder.SENT, isDeleted: false, isRead: false }, + }), + // TRASH total (isDeleted = true) + prisma.cachedEmail.count({ + where: { stressfreiEmailId, isDeleted: true }, + }), + // TRASH unread + prisma.cachedEmail.count({ + where: { stressfreiEmailId, isDeleted: true, isRead: false }, + }), + ]); + + return { inbox, inboxUnread, sent, sentUnread, trash, trashUnread }; +} + +// E-Mail-Anzahl pro Ordner für einen Vertrag (zugeordnete E-Mails) +export async function getFolderCountsForContract(contractId: number): Promise<{ + inbox: number; + inboxUnread: number; + sent: number; + sentUnread: number; +}> { + const [inbox, inboxUnread, sent, sentUnread] = await Promise.all([ + // INBOX total + prisma.cachedEmail.count({ + where: { contractId, folder: EmailFolder.INBOX, isDeleted: false }, + }), + // INBOX unread + prisma.cachedEmail.count({ + where: { contractId, folder: EmailFolder.INBOX, isDeleted: false, isRead: false }, + }), + // SENT total + prisma.cachedEmail.count({ + where: { contractId, folder: EmailFolder.SENT, isDeleted: false }, + }), + // SENT unread + prisma.cachedEmail.count({ + where: { contractId, folder: EmailFolder.SENT, isDeleted: false, isRead: false }, + }), + ]); + + return { inbox, inboxUnread, sent, sentUnread }; +} + +// Alle StressfreiEmails eines Kunden mit Mailbox +export async function getMailboxAccountsForCustomer(customerId: number) { + return prisma.stressfreiEmail.findMany({ + where: { + customerId, + hasMailbox: true, + }, + select: { + id: true, + email: true, + notes: true, + _count: { + select: { + cachedEmails: true, + }, + }, + }, + orderBy: { email: 'asc' }, + }); +} + +// E-Mail-Thread finden (basierend auf References/In-Reply-To) +export async function getEmailThread(emailId: number): Promise { + const email = await prisma.cachedEmail.findUnique({ + where: { id: emailId }, + }); + + if (!email) { + return []; + } + + // Suche nach E-Mails mit dem gleichen Betreff (vereinfachte Thread-Logik) + // In einer vollständigen Implementierung würde man References/In-Reply-To parsen + const baseSubject = email.subject?.replace(/^(Re|Fwd|Aw|Wg):\s*/gi, '') || ''; + + if (!baseSubject) { + return [email as CachedEmailWithRelations]; + } + + const thread = await prisma.cachedEmail.findMany({ + where: { + stressfreiEmailId: email.stressfreiEmailId, + OR: [ + { subject: baseSubject }, + { subject: { startsWith: `Re: ${baseSubject}` } }, + { subject: { startsWith: `Aw: ${baseSubject}` } }, + { subject: { startsWith: `Fwd: ${baseSubject}` } }, + { subject: { startsWith: `Wg: ${baseSubject}` } }, + ], + }, + include: { + stressfreiEmail: { + select: { + id: true, + email: true, + customerId: true, + }, + }, + contract: { + select: { + id: true, + contractNumber: true, + }, + }, + }, + orderBy: { receivedAt: 'asc' }, + }); + + return thread as CachedEmailWithRelations[]; +} + +// ==================== TRASH OPERATIONS ==================== + +export interface TrashOperationResult { + success: boolean; + error?: string; +} + +// E-Mail in Papierkorb verschieben (markiert als gelöscht + IMAP-Move) +export async function moveEmailToTrash(id: number): Promise { + // E-Mail mit StressfreiEmail laden + const email = await prisma.cachedEmail.findUnique({ + where: { id }, + include: { + stressfreiEmail: true, + }, + }); + + if (!email) { + return { success: false, error: 'E-Mail nicht gefunden' }; + } + + if (email.isDeleted) { + return { success: false, error: 'E-Mail ist bereits im Papierkorb' }; + } + + // IMAP-Einstellungen und Credentials laden + const settings = await getImapSmtpSettings(); + if (!settings) { + return { success: false, error: 'Keine E-Mail-Provider-Einstellungen' }; + } + + if (!email.stressfreiEmail.emailPasswordEncrypted) { + return { success: false, error: 'Keine Mailbox-Zugangsdaten' }; + } + + let password: string; + try { + password = decrypt(email.stressfreiEmail.emailPasswordEncrypted); + } catch { + return { success: false, error: 'Passwort konnte nicht entschlüsselt werden' }; + } + + const credentials: ImapCredentials = { + host: settings.imapServer, + port: settings.imapPort, + user: email.stressfreiEmail.email, + password, + encryption: settings.imapEncryption, + allowSelfSignedCerts: settings.allowSelfSignedCerts, + }; + + // Ordner bestimmen (INBOX oder Sent) + const sourceFolder = email.folder === 'SENT' ? 'Sent' : 'INBOX'; + + // Auf IMAP-Server in Trash verschieben + const imapResult = await moveToTrash(credentials, email.uid, sourceFolder); + + if (!imapResult.success) { + return { success: false, error: imapResult.error || 'IMAP-Fehler beim Verschieben' }; + } + + // In DB als gelöscht markieren (mit neuer UID im Trash) + await prisma.cachedEmail.update({ + where: { id }, + data: { + isDeleted: true, + deletedAt: new Date(), + uid: imapResult.newUid || email.uid, // Neue UID im Trash speichern + }, + }); + + return { success: true }; +} + +// E-Mail aus Papierkorb wiederherstellen +export async function restoreEmailFromTrash(id: number): Promise { + // E-Mail laden + const email = await prisma.cachedEmail.findUnique({ + where: { id }, + include: { + stressfreiEmail: true, + }, + }); + + if (!email) { + return { success: false, error: 'E-Mail nicht gefunden' }; + } + + if (!email.isDeleted) { + return { success: false, error: 'E-Mail ist nicht im Papierkorb' }; + } + + // IMAP-Einstellungen und Credentials + const settings = await getImapSmtpSettings(); + if (!settings) { + return { success: false, error: 'Keine E-Mail-Provider-Einstellungen' }; + } + + if (!email.stressfreiEmail.emailPasswordEncrypted) { + return { success: false, error: 'Keine Mailbox-Zugangsdaten' }; + } + + let password: string; + try { + password = decrypt(email.stressfreiEmail.emailPasswordEncrypted); + } catch { + return { success: false, error: 'Passwort konnte nicht entschlüsselt werden' }; + } + + const credentials: ImapCredentials = { + host: settings.imapServer, + port: settings.imapPort, + user: email.stressfreiEmail.email, + password, + encryption: settings.imapEncryption, + allowSelfSignedCerts: settings.allowSelfSignedCerts, + }; + + // Ziel-Ordner bestimmen (basierend auf originalem Ordner) + const targetFolder = email.folder === 'SENT' ? 'Sent' : 'INBOX'; + + // Auf IMAP-Server aus Trash wiederherstellen + const imapResult = await restoreFromTrash(credentials, email.uid, targetFolder); + + if (!imapResult.success) { + return { success: false, error: imapResult.error || 'IMAP-Fehler beim Wiederherstellen' }; + } + + // In DB als wiederhergestellt markieren + await prisma.cachedEmail.update({ + where: { id }, + data: { + isDeleted: false, + deletedAt: null, + uid: imapResult.newUid || email.uid, // Neue UID im wiederhergestellten Ordner + }, + }); + + return { success: true }; +} + +// E-Mail endgültig löschen (aus Papierkorb) +export async function permanentDeleteEmail(id: number): Promise { + // E-Mail laden + const email = await prisma.cachedEmail.findUnique({ + where: { id }, + include: { + stressfreiEmail: true, + }, + }); + + if (!email) { + return { success: false, error: 'E-Mail nicht gefunden' }; + } + + if (!email.isDeleted) { + return { success: false, error: 'E-Mail muss erst in den Papierkorb verschoben werden' }; + } + + // IMAP-Einstellungen und Credentials + const settings = await getImapSmtpSettings(); + if (!settings) { + return { success: false, error: 'Keine E-Mail-Provider-Einstellungen' }; + } + + if (!email.stressfreiEmail.emailPasswordEncrypted) { + return { success: false, error: 'Keine Mailbox-Zugangsdaten' }; + } + + let password: string; + try { + password = decrypt(email.stressfreiEmail.emailPasswordEncrypted); + } catch { + return { success: false, error: 'Passwort konnte nicht entschlüsselt werden' }; + } + + const credentials: ImapCredentials = { + host: settings.imapServer, + port: settings.imapPort, + user: email.stressfreiEmail.email, + password, + encryption: settings.imapEncryption, + allowSelfSignedCerts: settings.allowSelfSignedCerts, + }; + + // Auf IMAP-Server endgültig löschen (aus Trash) + const imapResult = await permanentDelete(credentials, email.uid); + + if (!imapResult.success) { + return { success: false, error: imapResult.error || 'IMAP-Fehler beim endgültigen Löschen' }; + } + + // Aus DB löschen + await prisma.cachedEmail.delete({ + where: { id }, + }); + + return { success: true }; +} + +// Papierkorb-E-Mails für einen Kunden abrufen +export async function getTrashEmails(customerId: number): Promise { + return prisma.cachedEmail.findMany({ + where: { + isDeleted: true, + stressfreiEmail: { + customerId, + }, + }, + include: { + stressfreiEmail: { + select: { + id: true, + email: true, + customerId: true, + }, + }, + contract: { + select: { + id: true, + contractNumber: true, + }, + }, + }, + orderBy: { deletedAt: 'desc' }, + }) as Promise; +} + +// Papierkorb-E-Mails zählen +export async function getTrashCount(customerId: number): Promise { + return prisma.cachedEmail.count({ + where: { + isDeleted: true, + stressfreiEmail: { + customerId, + }, + }, + }); +} + +// Legacy: E-Mail löschen (jetzt deprecated, nutze moveEmailToTrash) +export async function deleteCachedEmail(id: number): Promise { + // Zur Abwärtskompatibilität: In Papierkorb verschieben statt löschen + const result = await moveEmailToTrash(id); + if (!result.success) { + throw new Error(result.error || 'Fehler beim Löschen'); + } +} + +// Alle gecachten E-Mails für eine StressfreiEmail löschen (nur Cache, kein IMAP) +export async function clearCacheForAccount(stressfreiEmailId: number): Promise { + const result = await prisma.cachedEmail.deleteMany({ + where: { stressfreiEmailId }, + }); + return result.count; +} + +// ==================== SENT EMAILS ==================== + +// Gesendete E-Mail speichern +export async function createSentEmail( + stressfreiEmailId: number, + params: SentEmailParams +): Promise { + // StressfreiEmail laden um Absender-Info zu bekommen + const stressfreiEmail = await prisma.stressfreiEmail.findUnique({ + where: { id: stressfreiEmailId }, + select: { email: true }, + }); + + if (!stressfreiEmail) { + throw new Error('StressfreiEmail nicht gefunden'); + } + + const hasAttachments = params.attachmentNames && params.attachmentNames.length > 0; + + const email = await prisma.cachedEmail.create({ + data: { + stressfreiEmailId, + folder: EmailFolder.SENT, + messageId: params.messageId, + uid: params.uid || 0, // UID vom IMAP Sent-Ordner (für Attachment-Download) + subject: params.subject || null, + fromAddress: stressfreiEmail.email, + fromName: null, + toAddresses: JSON.stringify(params.to), + ccAddresses: params.cc && params.cc.length > 0 ? JSON.stringify(params.cc) : null, + receivedAt: new Date(), // Sendezeitpunkt + textBody: params.text || null, + htmlBody: params.html || null, + hasAttachments: hasAttachments || false, + attachmentNames: hasAttachments ? JSON.stringify(params.attachmentNames) : null, + isRead: true, // Gesendete sind immer "gelesen" + isStarred: false, + // Vertragszuordnung falls angegeben (automatisch = aus Vertrag gesendet) + contractId: params.contractId || null, + assignedAt: params.contractId ? new Date() : null, + isAutoAssigned: params.contractId ? true : false, // Automatisch wenn aus Vertrag gesendet + }, + }); + + return email; +} + +// Anzahl E-Mails für Konto nach Ordner +export async function getEmailCountByFolder( + stressfreiEmailId: number, + folder: 'INBOX' | 'SENT' +): Promise { + return prisma.cachedEmail.count({ + where: { + stressfreiEmailId, + folder: folder === 'SENT' ? EmailFolder.SENT : EmailFolder.INBOX, + }, + }); +} diff --git a/backend/src/services/emailProvider/emailProviderService.ts b/backend/src/services/emailProvider/emailProviderService.ts index 445a1683..0646c8cd 100644 --- a/backend/src/services/emailProvider/emailProviderService.ts +++ b/backend/src/services/emailProvider/emailProviderService.ts @@ -8,6 +8,7 @@ import { EmailExistsResult, EmailOperationResult, CreateEmailParams, + MailEncryption, } from './types.js'; import { PleskEmailProvider } from './pleskProvider.js'; @@ -68,6 +69,10 @@ export interface CreateProviderConfigData { password?: string; domain: string; defaultForwardEmail?: string; + // Verschlüsselungs-Einstellungen + imapEncryption?: MailEncryption; + smtpEncryption?: MailEncryption; + allowSelfSignedCerts?: boolean; isActive?: boolean; isDefault?: boolean; } @@ -95,6 +100,9 @@ export async function createProviderConfig(data: CreateProviderConfigData) { passwordEncrypted, domain: data.domain, defaultForwardEmail: data.defaultForwardEmail || null, + imapEncryption: data.imapEncryption ?? 'SSL', + smtpEncryption: data.smtpEncryption ?? 'SSL', + allowSelfSignedCerts: data.allowSelfSignedCerts ?? false, isActive: data.isActive ?? true, isDefault: data.isDefault ?? false, }, @@ -123,6 +131,9 @@ export async function updateProviderConfig( if (data.domain !== undefined) updateData.domain = data.domain; if (data.defaultForwardEmail !== undefined) updateData.defaultForwardEmail = data.defaultForwardEmail || null; + if (data.imapEncryption !== undefined) updateData.imapEncryption = data.imapEncryption; + if (data.smtpEncryption !== undefined) updateData.smtpEncryption = data.smtpEncryption; + if (data.allowSelfSignedCerts !== undefined) updateData.allowSelfSignedCerts = data.allowSelfSignedCerts; if (data.isActive !== undefined) updateData.isActive = data.isActive; if (data.isDefault !== undefined) updateData.isDefault = data.isDefault; @@ -179,6 +190,13 @@ async function getProviderInstance(): Promise { password, domain: dbConfig.domain, defaultForwardEmail: dbConfig.defaultForwardEmail || undefined, + imapServer: dbConfig.imapServer || undefined, + imapPort: dbConfig.imapPort || undefined, + smtpServer: dbConfig.smtpServer || undefined, + smtpPort: dbConfig.smtpPort || undefined, + imapEncryption: dbConfig.imapEncryption as MailEncryption, + smtpEncryption: dbConfig.smtpEncryption as MailEncryption, + allowSelfSignedCerts: dbConfig.allowSelfSignedCerts, isActive: dbConfig.isActive, isDefault: dbConfig.isDefault, }; @@ -239,6 +257,169 @@ export async function provisionEmail( } } +// E-Mail mit echter Mailbox erstellen (IMAP/SMTP-Zugang) +export async function provisionEmailWithMailbox( + localPart: string, + customerEmail: string, + password: string +): Promise { + try { + const provider = await getProviderInstance(); + const config = await getActiveProviderConfig(); + + // Weiterleitungsziele zusammenstellen + const forwardTargets: string[] = [customerEmail]; + + // Unsere eigene Weiterleitungsadresse hinzufügen falls konfiguriert + if (config?.defaultForwardEmail) { + forwardTargets.push(config.defaultForwardEmail); + } + + // Prüfen ob existiert + const exists = await provider.emailExists(localPart); + if (exists.exists) { + return { + success: true, + message: `E-Mail ${exists.email} existiert bereits`, + email: exists.email, + }; + } + + // Mit Mailbox erstellen + const result = await provider.createEmailWithMailbox({ + localPart, + forwardTargets, + password, + }); + + return result; + } catch (error) { + const errorMessage = error instanceof Error ? error.message : 'Unbekannter Fehler'; + return { + success: false, + error: errorMessage, + }; + } +} + +// Mailbox für existierende E-Mail-Weiterleitung aktivieren +export async function enableMailboxForExistingEmail( + localPart: string, + password: string +): Promise { + try { + const provider = await getProviderInstance(); + + const result = await provider.enableMailboxForExisting({ + localPart, + password, + }); + + return result; + } catch (error) { + const errorMessage = error instanceof Error ? error.message : 'Unbekannter Fehler'; + return { + success: false, + error: errorMessage, + }; + } +} + +// Mailbox-Passwort beim Provider aktualisieren +export async function updateMailboxPassword( + localPart: string, + password: string +): Promise { + try { + const provider = await getProviderInstance(); + + const result = await provider.updateMailboxPassword({ + localPart, + password, + }); + + return result; + } catch (error) { + const errorMessage = error instanceof Error ? error.message : 'Unbekannter Fehler'; + return { + success: false, + error: errorMessage, + }; + } +} + +// IMAP/SMTP-Einstellungen vom aktiven Provider holen +export interface ImapSmtpSettings { + imapServer: string; + imapPort: number; + imapEncryption: MailEncryption; // SSL, STARTTLS oder NONE + smtpServer: string; + smtpPort: number; + smtpEncryption: MailEncryption; // SSL, STARTTLS oder NONE + allowSelfSignedCerts: boolean; // Selbstsignierte Zertifikate erlauben + domain: string; +} + +export async function getImapSmtpSettings(): Promise { + const config = await getActiveProviderConfig(); + if (!config) return null; + + // Default-Server: Hostname aus der apiUrl extrahieren (z.B. rs001871.fastrootserver.de aus https://rs001871.fastrootserver.de:8443) + // Der Plesk-Server ist gleichzeitig der Mail-Server + let defaultServer: string; + try { + const url = new URL(config.apiUrl); + defaultServer = url.hostname; + } catch { + // Fallback falls apiUrl ungültig + defaultServer = `mail.${config.domain}`; + } + + // Verschlüsselungs-Einstellungen + const imapEncryption = (config.imapEncryption ?? 'SSL') as MailEncryption; + const smtpEncryption = (config.smtpEncryption ?? 'SSL') as MailEncryption; + + // Ports basierend auf Verschlüsselung berechnen: + // SSL: IMAP 993, SMTP 465 + // STARTTLS: IMAP 143, SMTP 587 + // NONE: IMAP 143, SMTP 25 + // + // Standard-Ports werden IMMER basierend auf Verschlüsselung berechnet. + // Nur benutzerdefinierte Ports (nicht 993/143/465/587/25) werden aus der DB übernommen. + const getImapPort = (enc: MailEncryption, storedPort: number | null) => { + const standardPorts = [993, 143]; + // Wenn ein nicht-standard Port gespeichert ist, diesen verwenden + if (storedPort && !standardPorts.includes(storedPort)) { + return storedPort; + } + // Sonst basierend auf Verschlüsselung + return enc === 'SSL' ? 993 : 143; + }; + + const getSmtpPort = (enc: MailEncryption, storedPort: number | null) => { + const standardPorts = [465, 587, 25]; + // Wenn ein nicht-standard Port gespeichert ist, diesen verwenden + if (storedPort && !standardPorts.includes(storedPort)) { + return storedPort; + } + // Sonst basierend auf Verschlüsselung + if (enc === 'SSL') return 465; + if (enc === 'STARTTLS') return 587; + return 25; // NONE + }; + + return { + imapServer: config.imapServer || defaultServer, + imapPort: getImapPort(imapEncryption, config.imapPort), + imapEncryption, + smtpServer: config.smtpServer || defaultServer, + smtpPort: getSmtpPort(smtpEncryption, config.smtpPort), + smtpEncryption, + allowSelfSignedCerts: config.allowSelfSignedCerts ?? false, + domain: config.domain, + }; +} + // E-Mail löschen export async function deprovisionEmail(localPart: string): Promise { try { @@ -328,6 +509,13 @@ async function getProviderInstanceById(id: number): Promise { password, domain: dbConfig.domain, defaultForwardEmail: dbConfig.defaultForwardEmail || undefined, + imapServer: dbConfig.imapServer || undefined, + imapPort: dbConfig.imapPort || undefined, + smtpServer: dbConfig.smtpServer || undefined, + smtpPort: dbConfig.smtpPort || undefined, + imapEncryption: dbConfig.imapEncryption as MailEncryption, + smtpEncryption: dbConfig.smtpEncryption as MailEncryption, + allowSelfSignedCerts: dbConfig.allowSelfSignedCerts, isActive: dbConfig.isActive, isDefault: dbConfig.isDefault, }; diff --git a/backend/src/services/emailProvider/pleskProvider.ts b/backend/src/services/emailProvider/pleskProvider.ts index e3743844..55644202 100644 --- a/backend/src/services/emailProvider/pleskProvider.ts +++ b/backend/src/services/emailProvider/pleskProvider.ts @@ -7,6 +7,10 @@ import { EmailExistsResult, EmailOperationResult, CreateEmailParams, + CreateEmailWithMailboxParams, + CreateEmailWithMailboxResult, + EnableMailboxParams, + UpdateMailboxPasswordParams, RenameEmailParams, } from './types.js'; @@ -173,9 +177,20 @@ export class PleskEmailProvider implements IEmailProvider { // stdout sollte die Mail-Infos enthalten const exists = result.stdout?.toLowerCase().includes(localPart.toLowerCase()); + + // Mailbox-Status aus stdout parsen (Format: "Mailbox: true" oder "Mailbox: false") + let hasMailbox: boolean | undefined; + if (exists && result.stdout) { + const mailboxMatch = result.stdout.match(/Mailbox:\s*(true|false)/i); + if (mailboxMatch) { + hasMailbox = mailboxMatch[1].toLowerCase() === 'true'; + } + } + return { exists, email: exists ? email : undefined, + hasMailbox, }; } catch (error) { // HTTP-Fehler oder Netzwerkfehler @@ -231,6 +246,127 @@ export class PleskEmailProvider implements IEmailProvider { } } + async createEmailWithMailbox(params: CreateEmailWithMailboxParams): Promise { + const { localPart, forwardTargets, password } = params; + const email = `${localPart}@${this.config.domain}`; + + try { + // Prüfen ob schon existiert + const exists = await this.emailExists(localPart); + if (exists.exists) { + return { + success: false, + error: `E-Mail ${email} existiert bereits`, + }; + } + + // Plesk CLI API: Mail-Account mit echter Mailbox erstellen + // -mailbox true: Echte Mailbox (IMAP/SMTP-Zugang) + // -passwd: Passwort für die Mailbox + // -forwarding true: Zusätzlich Weiterleitung aktivieren + await this.request('POST', '/api/v2/cli/mail/call', { + params: [ + '--create', email, + '-mailbox', 'true', + '-passwd', password, + '-forwarding', 'true', + '-forwarding-addresses', `add:${forwardTargets.join(',')}`, + ], + }); + + return { + success: true, + message: `E-Mail ${email} mit Mailbox erfolgreich erstellt`, + email, + }; + } catch (error) { + const errorMessage = error instanceof Error ? error.message : 'Unbekannter Fehler'; + console.error('Plesk createEmailWithMailbox error:', error); + return { + success: false, + error: `Fehler beim Erstellen der E-Mail mit Mailbox: ${errorMessage}`, + }; + } + } + + async enableMailboxForExisting(params: EnableMailboxParams): Promise { + const { localPart, password } = params; + const email = `${localPart}@${this.config.domain}`; + + try { + // Prüfen ob E-Mail existiert + const exists = await this.emailExists(localPart); + if (!exists.exists) { + return { + success: false, + error: `E-Mail ${email} nicht gefunden`, + }; + } + + // Plesk CLI API: Mailbox für existierende E-Mail aktivieren + // --update: Existierende E-Mail aktualisieren + // -mailbox true: Mailbox aktivieren + // -passwd: Passwort für die Mailbox setzen + await this.request('POST', '/api/v2/cli/mail/call', { + params: [ + '--update', email, + '-mailbox', 'true', + '-passwd', password, + ], + }); + + return { + success: true, + message: `Mailbox für ${email} erfolgreich aktiviert`, + }; + } catch (error) { + const errorMessage = error instanceof Error ? error.message : 'Unbekannter Fehler'; + console.error('Plesk enableMailboxForExisting error:', error); + return { + success: false, + error: `Fehler beim Aktivieren der Mailbox: ${errorMessage}`, + }; + } + } + + async updateMailboxPassword(params: UpdateMailboxPasswordParams): Promise { + const { localPart, password } = params; + const email = `${localPart}@${this.config.domain}`; + + try { + // Prüfen ob E-Mail existiert + const exists = await this.emailExists(localPart); + if (!exists.exists) { + return { + success: false, + error: `E-Mail ${email} nicht gefunden`, + }; + } + + // Plesk CLI API: Passwort für existierende E-Mail aktualisieren + // --update: Existierende E-Mail aktualisieren + // -passwd: Neues Passwort setzen + await this.request('POST', '/api/v2/cli/mail/call', { + params: [ + '--update', email, + '-passwd', password, + ], + }); + + return { + success: true, + message: `Passwort für ${email} erfolgreich aktualisiert`, + }; + } catch (error) { + const errorMessage = error instanceof Error ? error.message : 'Unbekannter Fehler'; + console.error('Plesk updateMailboxPassword error:', error); + return { + success: false, + error: `Fehler beim Aktualisieren des Passworts: ${errorMessage}`, + }; + } + } + async deleteEmail(localPart: string): Promise { const email = `${localPart}@${this.config.domain}`; diff --git a/backend/src/services/emailProvider/types.ts b/backend/src/services/emailProvider/types.ts index 35f24436..5f78446e 100644 --- a/backend/src/services/emailProvider/types.ts +++ b/backend/src/services/emailProvider/types.ts @@ -1,5 +1,8 @@ // ==================== EMAIL PROVIDER TYPES ==================== +// Verschlüsselungstyp für E-Mail-Verbindungen +export type MailEncryption = 'SSL' | 'STARTTLS' | 'NONE'; + export interface EmailForwardTarget { email: string; } @@ -9,6 +12,27 @@ export interface CreateEmailParams { forwardTargets: string[]; // Weiterleitungsziele } +export interface CreateEmailWithMailboxParams { + localPart: string; // z.B. "max.mustermann" + forwardTargets: string[]; // Weiterleitungsziele + password: string; // Passwort für Mailbox (IMAP/SMTP) +} + +export interface CreateEmailWithMailboxResult extends EmailOperationResult { + // Erfolg: Mailbox-Informationen zurückgeben + email?: string; // Vollständige E-Mail-Adresse +} + +export interface EnableMailboxParams { + localPart: string; // z.B. "max.mustermann" + password: string; // Passwort für Mailbox (IMAP/SMTP) +} + +export interface UpdateMailboxPasswordParams { + localPart: string; // z.B. "max.mustermann" + password: string; // Neues Passwort für Mailbox +} + export interface RenameEmailParams { oldLocalPart: string; newLocalPart: string; @@ -17,6 +41,7 @@ export interface RenameEmailParams { export interface EmailExistsResult { exists: boolean; email?: string; + hasMailbox?: boolean; // true wenn echte Mailbox vorhanden } export interface EmailOperationResult { @@ -36,9 +61,18 @@ export interface IEmailProvider { // Prüft ob eine E-Mail-Adresse existiert emailExists(localPart: string): Promise; - // Erstellt eine neue E-Mail-Weiterleitung + // Erstellt eine neue E-Mail-Weiterleitung (ohne Mailbox) createEmail(params: CreateEmailParams): Promise; + // Erstellt eine neue E-Mail mit echter Mailbox (IMAP/SMTP-Zugang) + createEmailWithMailbox(params: CreateEmailWithMailboxParams): Promise; + + // Aktiviert Mailbox für eine existierende E-Mail-Weiterleitung + enableMailboxForExisting(params: EnableMailboxParams): Promise; + + // Aktualisiert das Passwort einer Mailbox + updateMailboxPassword(params: UpdateMailboxPasswordParams): Promise; + // Löscht eine E-Mail-Adresse deleteEmail(localPart: string): Promise; @@ -60,6 +94,15 @@ export interface EmailProviderConfig { password?: string; // Entschlüsselt domain: string; defaultForwardEmail?: string; + // IMAP/SMTP-Server für E-Mail-Client (optional, default: mail.{domain}) + imapServer?: string; + imapPort?: number; + smtpServer?: string; + smtpPort?: number; + // Verschlüsselungs-Einstellungen + imapEncryption?: MailEncryption; // SSL, STARTTLS oder NONE + smtpEncryption?: MailEncryption; // SSL, STARTTLS oder NONE + allowSelfSignedCerts?: boolean; // Selbstsignierte Zertifikate erlauben isActive: boolean; isDefault: boolean; } diff --git a/backend/src/services/imapService.ts b/backend/src/services/imapService.ts new file mode 100644 index 00000000..f44cb30b --- /dev/null +++ b/backend/src/services/imapService.ts @@ -0,0 +1,825 @@ +// ==================== IMAP SERVICE ==================== +// Service für IMAP-Zugriff auf Mailboxen + +import { ImapFlow, FetchMessageObject } from 'imapflow'; +import { simpleParser, ParsedMail, AddressObject } from 'mailparser'; + +// Verschlüsselungstyp +export type MailEncryption = 'SSL' | 'STARTTLS' | 'NONE'; + +export interface ImapCredentials { + host: string; + port: number; + user: string; + password: string; + encryption?: MailEncryption; // SSL, STARTTLS oder NONE (Standard: SSL) + allowSelfSignedCerts?: boolean; // Selbstsignierte Zertifikate erlauben +} + +export interface FetchedEmail { + uid: number; + messageId: string; + subject: string | null; + fromAddress: string; + fromName: string | null; + toAddresses: string[]; + ccAddresses: string[]; + date: Date; + textBody: string | null; + htmlBody: string | null; + hasAttachments: boolean; + attachmentNames: string[]; +} + +export interface FetchOptions { + folder?: string; // Default: 'INBOX' + since?: Date; // Nur E-Mails nach diesem Datum + limit?: number; // Max. Anzahl E-Mails + sinceUid?: number; // Nur E-Mails ab dieser UID (für inkrementellen Sync) +} + +// Helper: Adressen aus mailparser-Format extrahieren +function extractAddresses(addressObj: AddressObject | AddressObject[] | undefined): string[] { + if (!addressObj) return []; + + const addresses = Array.isArray(addressObj) ? addressObj : [addressObj]; + const result: string[] = []; + + for (const obj of addresses) { + if (obj.value) { + for (const addr of obj.value) { + if (addr.address) { + result.push(addr.address); + } + } + } + } + + return result; +} + +// Helper: Ersten Absender-Namen extrahieren +function extractFromName(addressObj: AddressObject | AddressObject[] | undefined): string | null { + if (!addressObj) return null; + + const addresses = Array.isArray(addressObj) ? addressObj : [addressObj]; + + for (const obj of addresses) { + if (obj.value && obj.value[0]) { + return obj.value[0].name || null; + } + } + + return null; +} + +// E-Mails aus einer Mailbox abrufen +export async function fetchEmails( + credentials: ImapCredentials, + options: FetchOptions = {} +): Promise { + const { + folder = 'INBOX', + since, + limit = 50, + sinceUid, + } = options; + + // Verschlüsselungs-Einstellungen basierend auf Modus + const encryption = credentials.encryption ?? 'SSL'; + const rejectUnauthorized = !credentials.allowSelfSignedCerts; + + // ImapFlow-Optionen je nach Verschlüsselungstyp + // SSL: secure=true (implicit TLS, Port 993) + // STARTTLS: secure=false (upgrades to TLS, Port 143) + // NONE: secure=false + disableAutoIdle (no encryption, Port 143) + const clientOptions: ConstructorParameters[0] = { + host: credentials.host, + port: credentials.port, + secure: encryption === 'SSL', + auth: { + user: credentials.user, + pass: credentials.password, + }, + logger: false, + }; + + // TLS-Optionen nur wenn nicht NONE + if (encryption !== 'NONE') { + clientOptions.tls = { rejectUnauthorized }; + } + + // Debug-Logging + console.log(`[IMAP] Connecting to ${credentials.host}:${credentials.port} (${encryption}), user: ${credentials.user}`); + + const client = new ImapFlow(clientOptions); + + const emails: FetchedEmail[] = []; + + try { + await client.connect(); + console.log(`[IMAP] Connected successfully`); + + // Mailbox öffnen + await client.mailboxOpen(folder); + + // Suchkriterien zusammenstellen + let searchCriteria: { since?: Date; uid?: string } = {}; + + if (since) { + searchCriteria.since = since; + } + + // IMAP SEARCH ausführen + let uids: number[]; + + if (sinceUid) { + // Inkrementeller Sync: Nur E-Mails ab einer bestimmten UID + // IMAP UID-Range: "sinceUid:*" bedeutet alle E-Mails >= sinceUid + const messages = await client.search({ uid: `${sinceUid}:*` }, { uid: true }); + const messageArray = Array.isArray(messages) ? messages : []; + uids = messageArray.filter((uid: number) => uid > sinceUid); // Exkludiere die sinceUid selbst + } else if (since) { + // Nach Datum suchen + const messages = await client.search({ since }, { uid: true }); + uids = Array.isArray(messages) ? messages : []; + } else { + // Alle E-Mails (mit Limit) + const messages = await client.search({ all: true }, { uid: true }); + uids = Array.isArray(messages) ? messages : []; + } + + // Neueste zuerst (absteigend sortieren) + uids.sort((a, b) => b - a); + + // Limit anwenden + const limitedUids = uids.slice(0, limit); + + console.log(`[IMAP] Found ${uids.length} emails, fetching ${limitedUids.length}`); + + if (limitedUids.length === 0) { + console.log(`[IMAP] No emails to fetch`); + await client.logout(); + return []; + } + + // E-Mails abrufen + for await (const message of client.fetch(limitedUids, { + uid: true, + envelope: true, + source: true, // Vollständige E-Mail für Parsing + })) { + try { + // Source muss vorhanden sein + if (!message.source) { + console.error(`E-Mail UID ${message.uid} hat keine Source`); + continue; + } + + // E-Mail mit mailparser parsen + const parsed = await simpleParser(message.source) as ParsedMail; + + const email: FetchedEmail = { + uid: message.uid, + messageId: parsed.messageId || `${message.uid}@unknown`, + subject: parsed.subject || null, + fromAddress: extractAddresses(parsed.from)[0] || 'unknown@unknown', + fromName: extractFromName(parsed.from), + toAddresses: extractAddresses(parsed.to), + ccAddresses: extractAddresses(parsed.cc), + date: parsed.date || new Date(), + textBody: parsed.text || null, + htmlBody: parsed.html ? String(parsed.html) : null, + hasAttachments: (parsed.attachments?.length || 0) > 0, + attachmentNames: parsed.attachments?.map((a) => a.filename || 'unnamed') || [], + }; + + emails.push(email); + } catch (parseError) { + console.error(`Fehler beim Parsen von E-Mail UID ${message.uid}:`, parseError); + // E-Mail überspringen bei Parse-Fehlern + } + } + + await client.logout(); + } catch (error) { + // Verbindung sauber schließen bei Fehlern + try { + await client.logout(); + } catch { + // Ignorieren + } + + // Bessere Fehlermeldungen + if (error instanceof Error) { + const msg = error.message.toLowerCase(); + const errorCode = (error as NodeJS.ErrnoException).code?.toLowerCase() || ''; + + if (msg.includes('authentication') || msg.includes('login')) { + throw new Error('IMAP-Authentifizierung fehlgeschlagen - Zugangsdaten prüfen'); + } + if (msg.includes('econnrefused') || errorCode === 'econnrefused') { + throw new Error(`IMAP-Server nicht erreichbar: ${credentials.host}:${credentials.port} - Verbindung verweigert`); + } + if (msg.includes('timeout') || msg.includes('etimedout') || errorCode === 'etimedout') { + const enc = credentials.encryption ?? 'SSL'; + if (enc === 'STARTTLS' && credentials.port === 143) { + throw new Error(`IMAP Port 143 (STARTTLS) nicht erreichbar auf ${credentials.host}`); + } else if (enc === 'SSL' && credentials.port === 993) { + throw new Error(`IMAP Port 993 (SSL) nicht erreichbar auf ${credentials.host}`); + } else { + throw new Error(`IMAP-Verbindung zu ${credentials.host}:${credentials.port} fehlgeschlagen - Timeout`); + } + } + if (msg.includes('certificate') || msg.includes('cert')) { + throw new Error('IMAP SSL-Zertifikatfehler - Aktiviere "Selbstsignierte Zertifikate erlauben"'); + } + } + + throw error; + } + + return emails; +} + +// Verbindung testen +export async function testImapConnection(credentials: ImapCredentials): Promise { + // Verschlüsselungs-Einstellungen basierend auf Modus + const encryption = credentials.encryption ?? 'SSL'; + const rejectUnauthorized = !credentials.allowSelfSignedCerts; + + const clientOptions: ConstructorParameters[0] = { + host: credentials.host, + port: credentials.port, + secure: encryption === 'SSL', + auth: { + user: credentials.user, + pass: credentials.password, + }, + logger: false, + }; + + if (encryption !== 'NONE') { + clientOptions.tls = { rejectUnauthorized }; + } + + const client = new ImapFlow(clientOptions); + + try { + await client.connect(); + await client.logout(); + } catch (error) { + // Verbindung sauber schließen bei Fehlern + try { + await client.logout(); + } catch { + // Ignorieren + } + + if (error instanceof Error) { + const msg = error.message.toLowerCase(); + const errorCode = (error as NodeJS.ErrnoException).code?.toLowerCase() || ''; + + if (msg.includes('authentication') || msg.includes('login')) { + throw new Error('IMAP-Authentifizierung fehlgeschlagen'); + } + if (msg.includes('econnrefused') || errorCode === 'econnrefused') { + throw new Error(`IMAP-Server nicht erreichbar: ${credentials.host}:${credentials.port} - Verbindung verweigert`); + } + if (msg.includes('timeout') || msg.includes('etimedout') || errorCode === 'etimedout') { + if (encryption === 'STARTTLS' && credentials.port === 143) { + throw new Error(`IMAP Port 143 (STARTTLS) nicht erreichbar auf ${credentials.host}`); + } else if (encryption === 'SSL' && credentials.port === 993) { + throw new Error(`IMAP Port 993 (SSL) nicht erreichbar auf ${credentials.host}`); + } else { + throw new Error(`IMAP-Verbindung zu ${credentials.host}:${credentials.port} fehlgeschlagen - Timeout`); + } + } + if (msg.includes('certificate') || msg.includes('cert')) { + throw new Error('IMAP SSL-Zertifikatfehler - Aktiviere "Selbstsignierte Zertifikate erlauben"'); + } + } + + throw error; + } +} + +// Höchste UID in einer Mailbox ermitteln (für inkrementellen Sync) +export async function getHighestUid( + credentials: ImapCredentials, + folder: string = 'INBOX' +): Promise { + // Verschlüsselungs-Einstellungen basierend auf Modus + const encryption = credentials.encryption ?? 'SSL'; + const rejectUnauthorized = !credentials.allowSelfSignedCerts; + + const clientOptions: ConstructorParameters[0] = { + host: credentials.host, + port: credentials.port, + secure: encryption === 'SSL', + auth: { + user: credentials.user, + pass: credentials.password, + }, + logger: false, + }; + + if (encryption !== 'NONE') { + clientOptions.tls = { rejectUnauthorized }; + } + + const client = new ImapFlow(clientOptions); + + try { + await client.connect(); + const mailbox = await client.mailboxOpen(folder); + const highestUid = mailbox.uidNext ? mailbox.uidNext - 1 : 0; + await client.logout(); + return highestUid; + } catch (error) { + try { + await client.logout(); + } catch { + // Ignorieren + } + throw error; + } +} + +// Anhang-Interface +export interface EmailAttachmentData { + filename: string; + content: Buffer; + contentType: string; + size: number; +} + +// Anhang einer E-Mail per UID abrufen +export async function fetchAttachment( + credentials: ImapCredentials, + uid: number, + attachmentFilename: string, + folder: string = 'INBOX' +): Promise { + // Verschlüsselungs-Einstellungen basierend auf Modus + const encryption = credentials.encryption ?? 'SSL'; + const rejectUnauthorized = !credentials.allowSelfSignedCerts; + + const clientOptions: ConstructorParameters[0] = { + host: credentials.host, + port: credentials.port, + secure: encryption === 'SSL', + auth: { + user: credentials.user, + pass: credentials.password, + }, + logger: false, + }; + + if (encryption !== 'NONE') { + clientOptions.tls = { rejectUnauthorized }; + } + + const client = new ImapFlow(clientOptions); + + try { + await client.connect(); + await client.mailboxOpen(folder); + + // E-Mail per UID abrufen + let attachment: EmailAttachmentData | null = null; + + for await (const message of client.fetch([uid], { + uid: true, + source: true, + })) { + if (!message.source) continue; + + // E-Mail parsen + const parsed = await simpleParser(message.source); + + // Anhang suchen + if (parsed.attachments) { + for (const att of parsed.attachments) { + const filename = att.filename || 'unnamed'; + if (filename === attachmentFilename) { + attachment = { + filename, + content: att.content, + contentType: att.contentType || 'application/octet-stream', + size: att.size, + }; + break; + } + } + } + } + + await client.logout(); + return attachment; + } catch (error) { + try { + await client.logout(); + } catch { + // Ignorieren + } + throw error; + } +} + +// Gesendete E-Mail im IMAP Sent-Ordner speichern (für Attachment-Download) +export interface AppendToSentParams { + rawEmail: Buffer | string; // RFC 5322 formatierte E-Mail + sentFolder?: string; // Standard: 'Sent' +} + +export interface AppendToSentResult { + success: boolean; + uid?: number; // UID der gespeicherten Nachricht + error?: string; +} + +export async function appendToSent( + credentials: ImapCredentials, + params: AppendToSentParams +): Promise { + const { rawEmail, sentFolder = 'Sent' } = params; + const encryption = credentials.encryption ?? 'SSL'; + const rejectUnauthorized = !credentials.allowSelfSignedCerts; + + const clientOptions: ConstructorParameters[0] = { + host: credentials.host, + port: credentials.port, + secure: encryption === 'SSL', + auth: { + user: credentials.user, + pass: credentials.password, + }, + logger: false, + }; + + if (encryption !== 'NONE') { + clientOptions.tls = { rejectUnauthorized }; + } + + console.log(`[IMAP] Appending email to ${sentFolder} folder...`); + + const client = new ImapFlow(clientOptions); + + try { + await client.connect(); + + // E-Mail im Sent-Ordner speichern + const result = await client.append(sentFolder, rawEmail, ['\\Seen'], new Date()); + + await client.logout(); + + // append kann false zurückgeben bei Fehler + if (!result) { + return { success: false, error: 'IMAP append fehlgeschlagen' }; + } + + console.log(`[IMAP] Email appended successfully, UID: ${result.uid}`); + + return { + success: true, + uid: result.uid, + }; + } catch (error) { + try { + await client.logout(); + } catch { + // Ignorieren + } + + console.error('[IMAP] Error appending to Sent folder:', error); + + // Versuche mit alternativen Ordnernamen falls 'Sent' nicht existiert + if (sentFolder === 'Sent' && error instanceof Error) { + // Typische alternative Namen für Sent-Ordner + const alternativeNames = ['INBOX.Sent', 'Sent Messages', 'Sent Items']; + + for (const altFolder of alternativeNames) { + try { + const altClient = new ImapFlow(clientOptions); + await altClient.connect(); + const altResult = await altClient.append(altFolder, rawEmail, ['\\Seen'], new Date()); + await altClient.logout(); + + if (altResult) { + console.log(`[IMAP] Email appended to ${altFolder}, UID: ${altResult.uid}`); + return { success: true, uid: altResult.uid }; + } + } catch { + // Nächsten Namen versuchen + } + } + } + + return { + success: false, + error: error instanceof Error ? error.message : 'Fehler beim Speichern im Sent-Ordner', + }; + } +} + +// Alle Anhänge einer E-Mail per UID abrufen (Metadaten) +export async function fetchAttachmentList( + credentials: ImapCredentials, + uid: number, + folder: string = 'INBOX' +): Promise> { + // Verschlüsselungs-Einstellungen basierend auf Modus + const encryption = credentials.encryption ?? 'SSL'; + const rejectUnauthorized = !credentials.allowSelfSignedCerts; + + const clientOptions: ConstructorParameters[0] = { + host: credentials.host, + port: credentials.port, + secure: encryption === 'SSL', + auth: { + user: credentials.user, + pass: credentials.password, + }, + logger: false, + }; + + if (encryption !== 'NONE') { + clientOptions.tls = { rejectUnauthorized }; + } + + const client = new ImapFlow(clientOptions); + const attachments: Array<{ filename: string; contentType: string; size: number }> = []; + + try { + await client.connect(); + await client.mailboxOpen(folder); + + for await (const message of client.fetch([uid], { + uid: true, + source: true, + })) { + if (!message.source) continue; + + const parsed = await simpleParser(message.source); + + if (parsed.attachments) { + for (const att of parsed.attachments) { + attachments.push({ + filename: att.filename || 'unnamed', + contentType: att.contentType || 'application/octet-stream', + size: att.size, + }); + } + } + } + + await client.logout(); + return attachments; + } catch (error) { + try { + await client.logout(); + } catch { + // Ignorieren + } + throw error; + } +} + +// ==================== TRASH OPERATIONS ==================== + +// Typische Namen für Trash-Ordner (verschiedene Server/Sprachen) +const TRASH_FOLDER_NAMES = ['Trash', 'INBOX.Trash', 'Deleted', 'Deleted Items', 'Deleted Messages', 'Papierkorb']; + +// Helper: Trash-Ordner finden +async function findTrashFolder(client: ImapFlow): Promise { + const mailboxes = await client.list(); + + for (const name of TRASH_FOLDER_NAMES) { + const found = mailboxes.find(m => + m.path.toLowerCase() === name.toLowerCase() || + m.name.toLowerCase() === name.toLowerCase() + ); + if (found) return found.path; + } + + // Suche nach Ordner mit \Trash Flag + const trashByFlag = mailboxes.find(m => m.specialUse === '\\Trash'); + if (trashByFlag) return trashByFlag.path; + + return null; +} + +export interface MoveToTrashResult { + success: boolean; + newUid?: number; // UID im Trash-Ordner + error?: string; +} + +// E-Mail in Papierkorb verschieben +export async function moveToTrash( + credentials: ImapCredentials, + uid: number, + sourceFolder: string = 'INBOX' +): Promise { + const encryption = credentials.encryption ?? 'SSL'; + const rejectUnauthorized = !credentials.allowSelfSignedCerts; + + const clientOptions: ConstructorParameters[0] = { + host: credentials.host, + port: credentials.port, + secure: encryption === 'SSL', + auth: { + user: credentials.user, + pass: credentials.password, + }, + logger: false, + }; + + if (encryption !== 'NONE') { + clientOptions.tls = { rejectUnauthorized }; + } + + const client = new ImapFlow(clientOptions); + + try { + await client.connect(); + + // Trash-Ordner finden + const trashFolder = await findTrashFolder(client); + if (!trashFolder) { + await client.logout(); + return { success: false, error: 'Trash-Ordner nicht gefunden' }; + } + + // Source-Ordner öffnen + await client.mailboxOpen(sourceFolder); + + // E-Mail verschieben (kopieren + löschen) + const moveResult = await client.messageMove([uid], trashFolder, { uid: true }); + + await client.logout(); + + if (moveResult && moveResult.uidMap) { + // uidMap ist Map - alte UID -> neue UID + const newUid = moveResult.uidMap.get(uid); + console.log(`[IMAP] Email moved to ${trashFolder}, new UID: ${newUid}`); + return { success: true, newUid }; + } + + return { success: true }; + } catch (error) { + try { + await client.logout(); + } catch { + // Ignorieren + } + + console.error('[IMAP] Error moving to trash:', error); + return { + success: false, + error: error instanceof Error ? error.message : 'Fehler beim Verschieben in Papierkorb', + }; + } +} + +export interface RestoreFromTrashResult { + success: boolean; + newUid?: number; // UID im wiederhergestellten Ordner + error?: string; +} + +// E-Mail aus Papierkorb wiederherstellen +export async function restoreFromTrash( + credentials: ImapCredentials, + uid: number, + targetFolder: string = 'INBOX' +): Promise { + const encryption = credentials.encryption ?? 'SSL'; + const rejectUnauthorized = !credentials.allowSelfSignedCerts; + + const clientOptions: ConstructorParameters[0] = { + host: credentials.host, + port: credentials.port, + secure: encryption === 'SSL', + auth: { + user: credentials.user, + pass: credentials.password, + }, + logger: false, + }; + + if (encryption !== 'NONE') { + clientOptions.tls = { rejectUnauthorized }; + } + + const client = new ImapFlow(clientOptions); + + try { + await client.connect(); + + // Trash-Ordner finden + const trashFolder = await findTrashFolder(client); + if (!trashFolder) { + await client.logout(); + return { success: false, error: 'Trash-Ordner nicht gefunden' }; + } + + // Trash-Ordner öffnen + await client.mailboxOpen(trashFolder); + + // E-Mail zurück verschieben + const moveResult = await client.messageMove([uid], targetFolder, { uid: true }); + + await client.logout(); + + if (moveResult && moveResult.uidMap) { + const newUid = moveResult.uidMap.get(uid); + console.log(`[IMAP] Email restored to ${targetFolder}, new UID: ${newUid}`); + return { success: true, newUid }; + } + + return { success: true }; + } catch (error) { + try { + await client.logout(); + } catch { + // Ignorieren + } + + console.error('[IMAP] Error restoring from trash:', error); + return { + success: false, + error: error instanceof Error ? error.message : 'Fehler beim Wiederherstellen', + }; + } +} + +export interface PermanentDeleteResult { + success: boolean; + error?: string; +} + +// E-Mail endgültig löschen (aus Trash-Ordner) +export async function permanentDelete( + credentials: ImapCredentials, + uid: number, + folder?: string // Optional: Ordner angeben, sonst wird Trash verwendet +): Promise { + const encryption = credentials.encryption ?? 'SSL'; + const rejectUnauthorized = !credentials.allowSelfSignedCerts; + + const clientOptions: ConstructorParameters[0] = { + host: credentials.host, + port: credentials.port, + secure: encryption === 'SSL', + auth: { + user: credentials.user, + pass: credentials.password, + }, + logger: false, + }; + + if (encryption !== 'NONE') { + clientOptions.tls = { rejectUnauthorized }; + } + + const client = new ImapFlow(clientOptions); + + try { + await client.connect(); + + // Ordner bestimmen + let targetFolder: string | null | undefined = folder; + if (!targetFolder) { + targetFolder = await findTrashFolder(client); + if (!targetFolder) { + await client.logout(); + return { success: false, error: 'Trash-Ordner nicht gefunden' }; + } + } + + // Ordner öffnen + await client.mailboxOpen(targetFolder); + + // E-Mail als gelöscht markieren und expunge + await client.messageDelete([uid], { uid: true }); + + await client.logout(); + + console.log(`[IMAP] Email permanently deleted from ${targetFolder}, UID: ${uid}`); + return { success: true }; + } catch (error) { + try { + await client.logout(); + } catch { + // Ignorieren + } + + console.error('[IMAP] Error permanently deleting:', error); + return { + success: false, + error: error instanceof Error ? error.message : 'Fehler beim endgültigen Löschen', + }; + } +} diff --git a/backend/src/services/smtpService.ts b/backend/src/services/smtpService.ts new file mode 100644 index 00000000..355ad17a --- /dev/null +++ b/backend/src/services/smtpService.ts @@ -0,0 +1,304 @@ +// ==================== SMTP SERVICE ==================== +// Service für E-Mail-Versand via SMTP + +import nodemailer from 'nodemailer'; +import type { Transporter } from 'nodemailer'; +import MailComposer from 'nodemailer/lib/mail-composer'; + +// Verschlüsselungstyp +export type MailEncryption = 'SSL' | 'STARTTLS' | 'NONE'; + +export interface SmtpCredentials { + host: string; + port: number; + user: string; + password: string; + encryption?: MailEncryption; // SSL, STARTTLS oder NONE (Standard: SSL) + allowSelfSignedCerts?: boolean; // Selbstsignierte Zertifikate erlauben +} + +// Anhang-Interface +export interface EmailAttachment { + filename: string; + content: string; // Base64-kodierter Inhalt + contentType?: string; // MIME-Type (z.B. 'application/pdf') +} + +export interface SendEmailParams { + to: string | string[]; + cc?: string | string[]; + subject: string; + text?: string; + html?: string; + inReplyTo?: string; // Message-ID der E-Mail auf die geantwortet wird + references?: string[]; // Thread-Referenzen + attachments?: EmailAttachment[]; // Anhänge +} + +export interface SendEmailResult { + success: boolean; + messageId?: string; + rawEmail?: Buffer; // RFC 5322 formatierte E-Mail für IMAP-Speicherung + error?: string; +} + +// E-Mail senden +export async function sendEmail( + credentials: SmtpCredentials, + fromAddress: string, + params: SendEmailParams +): Promise { + // Verschlüsselungs-Einstellungen basierend auf Modus + const encryption = credentials.encryption ?? 'SSL'; + const rejectUnauthorized = !credentials.allowSelfSignedCerts; + + // Transport-Optionen je nach Verschlüsselungstyp + // SSL: secure=true (implicit TLS, Port 465) + // STARTTLS: secure=false (upgrades to TLS, Port 587) + // NONE: secure=false + ignoreTLS=true (no encryption, Port 25) + const transportOptions: nodemailer.TransportOptions & { + host: string; + port: number; + secure: boolean; + auth: { user: string; pass: string }; + tls?: { rejectUnauthorized: boolean }; + ignoreTLS?: boolean; + requireTLS?: boolean; + connectionTimeout: number; + greetingTimeout: number; + socketTimeout: number; + } = { + host: credentials.host, + port: credentials.port, + secure: encryption === 'SSL', + auth: { + user: credentials.user, + pass: credentials.password, + }, + connectionTimeout: 10000, + greetingTimeout: 10000, + socketTimeout: 30000, + }; + + // TLS-Optionen nur wenn nicht NONE + if (encryption !== 'NONE') { + transportOptions.tls = { rejectUnauthorized }; + } else { + // Keine Verschlüsselung: STARTTLS ignorieren + transportOptions.ignoreTLS = true; + } + + // Bei STARTTLS: requireTLS erzwingen + if (encryption === 'STARTTLS') { + transportOptions.requireTLS = true; + } + + // Debug-Logging für Entwicklung + console.log(`[SMTP] Connecting to ${credentials.host}:${credentials.port} (${encryption}), user: ${credentials.user}`); + + // Transporter erstellen + const transporter: Transporter = nodemailer.createTransport(transportOptions); + + try { + // E-Mail-Optionen zusammenstellen + const mailOptions: nodemailer.SendMailOptions = { + from: fromAddress, + to: Array.isArray(params.to) ? params.to.join(', ') : params.to, + subject: params.subject, + }; + + // CC hinzufügen falls vorhanden + if (params.cc) { + mailOptions.cc = Array.isArray(params.cc) ? params.cc.join(', ') : params.cc; + } + + // Body hinzufügen + if (params.html) { + mailOptions.html = params.html; + // Auch Text-Version für Clients ohne HTML-Support + mailOptions.text = params.text || stripHtml(params.html); + } else if (params.text) { + mailOptions.text = params.text; + } + + // Threading-Header für Antworten + if (params.inReplyTo) { + mailOptions.inReplyTo = params.inReplyTo; + } + if (params.references && params.references.length > 0) { + mailOptions.references = params.references.join(' '); + } + + // Anhänge hinzufügen + if (params.attachments && params.attachments.length > 0) { + mailOptions.attachments = params.attachments.map((att) => ({ + filename: att.filename, + content: Buffer.from(att.content, 'base64'), + contentType: att.contentType, + })); + } + + // E-Mail senden + const result = await transporter.sendMail(mailOptions); + + // Raw E-Mail für IMAP-Speicherung bauen (mit tatsächlicher Message-ID) + let rawEmail: Buffer | undefined; + try { + const composerOptions = { + ...mailOptions, + messageId: result.messageId, // Tatsächliche Message-ID vom Server + }; + const composer = new MailComposer(composerOptions); + rawEmail = await composer.compile().build(); + } catch (compileError) { + console.error('Error compiling raw email:', compileError); + // Nicht kritisch - E-Mail wurde trotzdem gesendet + } + + return { + success: true, + messageId: result.messageId, + rawEmail, + }; + } catch (error) { + console.error('SMTP sendEmail error:', error); + + // Bessere Fehlermeldungen + let errorMessage = 'Unbekannter Fehler beim E-Mail-Versand'; + + if (error instanceof Error) { + const msg = error.message.toLowerCase(); + const errorCode = (error as NodeJS.ErrnoException).code?.toLowerCase() || ''; + + if (msg.includes('authentication') || msg.includes('auth') || msg.includes('login')) { + errorMessage = 'SMTP-Authentifizierung fehlgeschlagen - Zugangsdaten prüfen'; + } else if (msg.includes('econnrefused') || errorCode === 'econnrefused') { + errorMessage = `SMTP-Server nicht erreichbar: ${credentials.host}:${credentials.port} - Verbindung verweigert`; + } else if (msg.includes('greeting never received') || msg.includes('etimedout') || errorCode === 'etimedout') { + // Detaillierte Fehlermeldung je nach Port/Verschlüsselung + const enc = credentials.encryption ?? 'SSL'; + if (enc === 'STARTTLS' && credentials.port === 587) { + errorMessage = `SMTP-Verbindung zu Port 587 fehlgeschlagen - STARTTLS (Submission) ist möglicherweise nicht aktiviert auf ${credentials.host}`; + } else if (enc === 'NONE' && credentials.port === 25) { + errorMessage = `SMTP-Verbindung zu Port 25 fehlgeschlagen - Port möglicherweise blockiert oder nicht erreichbar auf ${credentials.host}`; + } else { + errorMessage = `SMTP-Verbindung zu ${credentials.host}:${credentials.port} fehlgeschlagen - Port nicht erreichbar oder Timeout`; + } + } else if (msg.includes('timeout')) { + errorMessage = `SMTP-Verbindung: Zeitüberschreitung bei ${credentials.host}:${credentials.port}`; + } else if (msg.includes('recipient') || msg.includes('rejected')) { + errorMessage = 'Empfänger-Adresse wurde vom Server abgelehnt'; + } else if (msg.includes('certificate') || msg.includes('cert')) { + errorMessage = 'SSL-Zertifikatfehler - Aktiviere "Selbstsignierte Zertifikate erlauben" in den Provider-Einstellungen'; + } else if (msg.includes('socket close') || msg.includes('socket hang up') || msg.includes('econnreset') || errorCode === 'econnreset') { + // Server schließt Verbindung unerwartet - oft TLS-Problem bei STARTTLS + const enc = credentials.encryption ?? 'SSL'; + if (enc === 'STARTTLS') { + errorMessage = `SMTP-Verbindung abgebrochen bei STARTTLS - Aktiviere "Selbstsignierte Zertifikate erlauben" oder verwende SSL/TLS auf Port 465`; + } else { + errorMessage = `SMTP-Verbindung unerwartet geschlossen von ${credentials.host}:${credentials.port}`; + } + } else { + errorMessage = error.message; + } + } + + return { + success: false, + error: errorMessage, + }; + } finally { + // Transporter schließen + transporter.close(); + } +} + +// SMTP-Verbindung testen +export async function testSmtpConnection(credentials: SmtpCredentials): Promise { + // Verschlüsselungs-Einstellungen basierend auf Modus + const encryption = credentials.encryption ?? 'SSL'; + const rejectUnauthorized = !credentials.allowSelfSignedCerts; + + const transportOptions: nodemailer.TransportOptions & { + host: string; + port: number; + secure: boolean; + auth: { user: string; pass: string }; + tls?: { rejectUnauthorized: boolean }; + ignoreTLS?: boolean; + connectionTimeout: number; + greetingTimeout: number; + } = { + host: credentials.host, + port: credentials.port, + secure: encryption === 'SSL', + auth: { + user: credentials.user, + pass: credentials.password, + }, + connectionTimeout: 10000, + greetingTimeout: 10000, + }; + + if (encryption !== 'NONE') { + transportOptions.tls = { rejectUnauthorized }; + } else { + transportOptions.ignoreTLS = true; + } + + const transporter: Transporter = nodemailer.createTransport(transportOptions); + + try { + // Verbindung verifizieren + await transporter.verify(); + } catch (error) { + if (error instanceof Error) { + const msg = error.message.toLowerCase(); + const errorCode = (error as NodeJS.ErrnoException).code?.toLowerCase() || ''; + + if (msg.includes('authentication') || msg.includes('auth') || msg.includes('login')) { + throw new Error('SMTP-Authentifizierung fehlgeschlagen'); + } + if (msg.includes('econnrefused') || errorCode === 'econnrefused') { + throw new Error(`SMTP-Server nicht erreichbar: ${credentials.host}:${credentials.port} - Verbindung verweigert`); + } + if (msg.includes('greeting never received') || msg.includes('etimedout') || errorCode === 'etimedout') { + if (encryption === 'STARTTLS' && credentials.port === 587) { + throw new Error(`SMTP Port 587 (STARTTLS/Submission) ist nicht erreichbar - In Plesk unter Tools & Settings > Mail Server Settings aktivieren`); + } else if (encryption === 'NONE' && credentials.port === 25) { + throw new Error(`SMTP Port 25 ist nicht erreichbar auf ${credentials.host}`); + } else { + throw new Error(`SMTP-Verbindung zu ${credentials.host}:${credentials.port} fehlgeschlagen - Port nicht erreichbar`); + } + } + if (msg.includes('certificate') || msg.includes('cert')) { + throw new Error('SSL-Zertifikatfehler - Aktiviere "Selbstsignierte Zertifikate erlauben"'); + } + } + + throw error; + } finally { + transporter.close(); + } +} + +// Helper: HTML zu Text konvertieren (einfache Version) +function stripHtml(html: string): string { + return html + // Zeilenumbrüche für Block-Elemente + .replace(//gi, '\n') + .replace(/<\/p>/gi, '\n\n') + .replace(/<\/div>/gi, '\n') + .replace(/<\/li>/gi, '\n') + // Alle HTML-Tags entfernen + .replace(/<[^>]+>/g, '') + // HTML-Entities dekodieren + .replace(/ /g, ' ') + .replace(/&/g, '&') + .replace(/</g, '<') + .replace(/>/g, '>') + .replace(/"/g, '"') + // Mehrfache Leerzeilen reduzieren + .replace(/\n{3,}/g, '\n\n') + .trim(); +} diff --git a/backend/src/services/stressfreiEmail.service.ts b/backend/src/services/stressfreiEmail.service.ts index 2ee9e007..3b906af8 100644 --- a/backend/src/services/stressfreiEmail.service.ts +++ b/backend/src/services/stressfreiEmail.service.ts @@ -1,4 +1,14 @@ import { PrismaClient } from '@prisma/client'; +import { encrypt, decrypt } from '../utils/encryption.js'; +import { + provisionEmail, + provisionEmailWithMailbox, + enableMailboxForExistingEmail, + checkEmailExists, + getProviderDomain, + updateMailboxPassword, +} from './emailProvider/emailProviderService.js'; +import { generateSecurePassword } from '../utils/passwordGenerator.js'; const prisma = new PrismaClient(); @@ -13,22 +23,116 @@ export async function getEmailsByCustomerId(customerId: number, includeInactive }); } +// Mit Mailbox-Status für E-Mail-Client +export async function getEmailsWithMailboxByCustomerId(customerId: number) { + return prisma.stressfreiEmail.findMany({ + where: { + customerId, + isActive: true, + hasMailbox: true, + }, + select: { + id: true, + email: true, + notes: true, + hasMailbox: true, + _count: { + select: { + cachedEmails: true, + }, + }, + }, + orderBy: { email: 'asc' }, + }); +} + export async function getEmailById(id: number) { return prisma.stressfreiEmail.findUnique({ where: { id }, }); } -export async function createEmail(data: { +// E-Mail mit Mailbox-Status laden +export async function getEmailWithMailboxById(id: number) { + return prisma.stressfreiEmail.findUnique({ + where: { id }, + select: { + id: true, + customerId: true, + email: true, + platform: true, + notes: true, + isActive: true, + hasMailbox: true, + emailPasswordEncrypted: true, + createdAt: true, + updatedAt: true, + }, + }); +} + +export interface CreateEmailData { customerId: number; email: string; platform?: string; notes?: string; -}) { + provisionAtProvider?: boolean; + createMailbox?: boolean; +} + +export async function createEmail(data: CreateEmailData) { + const { provisionAtProvider, createMailbox, ...emailData } = data; + + // Falls beim Provider anlegen gewünscht + if (provisionAtProvider) { + // Kunde laden für Weiterleitung + const customer = await prisma.customer.findUnique({ + where: { id: data.customerId }, + select: { email: true }, + }); + + if (!customer?.email) { + throw new Error('Kunde hat keine E-Mail-Adresse für Weiterleitung'); + } + + // LocalPart extrahieren + const localPart = data.email.split('@')[0]; + + if (createMailbox) { + // Mit echter Mailbox anlegen + const password = generateSecurePassword(); + const result = await provisionEmailWithMailbox(localPart, customer.email, password); + + if (!result.success) { + throw new Error(result.error || 'Fehler beim Anlegen der Mailbox'); + } + + // Passwort verschlüsseln und speichern + const passwordEncrypted = encrypt(password); + + return prisma.stressfreiEmail.create({ + data: { + ...emailData, + isActive: true, + hasMailbox: true, + emailPasswordEncrypted: passwordEncrypted, + }, + }); + } else { + // Nur Weiterleitung anlegen + const result = await provisionEmail(localPart, customer.email); + + if (!result.success && !result.message?.includes('existiert bereits')) { + throw new Error(result.error || 'Fehler beim Anlegen der E-Mail'); + } + } + } + return prisma.stressfreiEmail.create({ data: { - ...data, + ...emailData, isActive: true, + hasMailbox: createMailbox || false, }, }); } @@ -51,3 +155,136 @@ export async function updateEmail( export async function deleteEmail(id: number) { return prisma.stressfreiEmail.delete({ where: { id } }); } + +// Mailbox nachträglich aktivieren (für existierende E-Mail-Weiterleitung) +export async function enableMailbox(id: number): Promise<{ success: boolean; error?: string }> { + const stressfreiEmail = await prisma.stressfreiEmail.findUnique({ + where: { id }, + }); + + if (!stressfreiEmail) { + return { success: false, error: 'StressfreiEmail nicht gefunden' }; + } + + if (stressfreiEmail.hasMailbox) { + return { success: false, error: 'Mailbox ist bereits aktiviert' }; + } + + const localPart = stressfreiEmail.email.split('@')[0]; + const password = generateSecurePassword(); + + // Mailbox für existierende E-Mail aktivieren (nicht neu erstellen!) + const result = await enableMailboxForExistingEmail(localPart, password); + + if (!result.success) { + return { success: false, error: result.error || 'Fehler beim Aktivieren der Mailbox' }; + } + + // Passwort verschlüsseln und speichern + const passwordEncrypted = encrypt(password); + + await prisma.stressfreiEmail.update({ + where: { id }, + data: { + hasMailbox: true, + emailPasswordEncrypted: passwordEncrypted, + }, + }); + + return { success: true }; +} + +// Mailbox-Status mit Provider synchronisieren +export async function syncMailboxStatus(id: number): Promise<{ + success: boolean; + hasMailbox?: boolean; + wasUpdated?: boolean; + error?: string +}> { + const stressfreiEmail = await prisma.stressfreiEmail.findUnique({ + where: { id }, + select: { email: true, hasMailbox: true }, + }); + + if (!stressfreiEmail) { + return { success: false, error: 'StressfreiEmail nicht gefunden' }; + } + + const localPart = stressfreiEmail.email.split('@')[0]; + + // Provider-Status prüfen + const providerStatus = await checkEmailExists(localPart); + + if (!providerStatus.exists) { + return { success: true, hasMailbox: false, wasUpdated: false }; + } + + const providerHasMailbox = providerStatus.hasMailbox === true; + + // DB aktualisieren wenn Status abweicht + if (stressfreiEmail.hasMailbox !== providerHasMailbox) { + await prisma.stressfreiEmail.update({ + where: { id }, + data: { hasMailbox: providerHasMailbox }, + }); + console.log(`Mailbox-Status für ${stressfreiEmail.email} aktualisiert: ${stressfreiEmail.hasMailbox} -> ${providerHasMailbox}`); + return { success: true, hasMailbox: providerHasMailbox, wasUpdated: true }; + } + + return { success: true, hasMailbox: providerHasMailbox, wasUpdated: false }; +} + +// Passwort für IMAP/SMTP-Zugang entschlüsseln (nur für autorisierte Nutzung) +export async function getDecryptedPassword(id: number): Promise { + const stressfreiEmail = await prisma.stressfreiEmail.findUnique({ + where: { id }, + select: { emailPasswordEncrypted: true }, + }); + + if (!stressfreiEmail?.emailPasswordEncrypted) { + return null; + } + + try { + return decrypt(stressfreiEmail.emailPasswordEncrypted); + } catch { + console.error('Fehler beim Entschlüsseln des Passworts'); + return null; + } +} + +// Passwort neu generieren und beim Provider setzen +export async function resetMailboxPassword(id: number): Promise<{ success: boolean; password?: string; error?: string }> { + const stressfreiEmail = await prisma.stressfreiEmail.findUnique({ + where: { id }, + select: { email: true, hasMailbox: true }, + }); + + if (!stressfreiEmail) { + return { success: false, error: 'StressfreiEmail nicht gefunden' }; + } + + if (!stressfreiEmail.hasMailbox) { + return { success: false, error: 'Keine Mailbox für diese E-Mail-Adresse' }; + } + + // Neues Passwort generieren + const newPassword = generateSecurePassword(); + const localPart = stressfreiEmail.email.split('@')[0]; + + // Passwort beim Provider ändern + const providerResult = await updateMailboxPassword(localPart, newPassword); + if (!providerResult.success) { + return { success: false, error: providerResult.error || 'Fehler beim Aktualisieren des Passworts beim Provider' }; + } + + // Passwort verschlüsseln und lokal speichern + const passwordEncrypted = encrypt(newPassword); + + await prisma.stressfreiEmail.update({ + where: { id }, + data: { emailPasswordEncrypted: passwordEncrypted }, + }); + + return { success: true, password: newPassword }; +} diff --git a/backend/src/services/user.service.ts b/backend/src/services/user.service.ts index c0d68eb6..5582e50b 100644 --- a/backend/src/services/user.service.ts +++ b/backend/src/services/user.service.ts @@ -134,10 +134,11 @@ export async function createUser(data: { lastName: string; roleIds: number[]; customerId?: number; + hasDeveloperAccess?: boolean; }) { const hashedPassword = await bcrypt.hash(data.password, 10); - return prisma.user.create({ + const user = await prisma.user.create({ data: { email: data.email, password: hashedPassword, @@ -160,6 +161,13 @@ export async function createUser(data: { }, }, }); + + // Entwicklerzugriff setzen falls aktiviert + if (data.hasDeveloperAccess) { + await setUserDeveloperAccess(user.id, true); + } + + return user; } export async function updateUser( @@ -270,10 +278,28 @@ export async function updateUser( (userData as Record).password = await bcrypt.hash(password, 10); } - // Update user + // Prüfen ob Rollen geändert werden (für Zwangslogout) + let rolesChanged = false; + if (roleIds !== undefined) { + const currentRoles = await prisma.userRole.findMany({ + where: { userId: id }, + select: { roleId: true }, + }); + const currentRoleIds = currentRoles.map((r) => r.roleId).sort(); + const newRoleIds = [...roleIds].sort(); + rolesChanged = + currentRoleIds.length !== newRoleIds.length || + !currentRoleIds.every((id, i) => id === newRoleIds[i]); + } + + // Update user - bei Rollenänderung Token invalidieren await prisma.user.update({ where: { id }, - data: userData, + data: { + ...userData, + // Token invalidieren wenn Rollen geändert werden + ...(rolesChanged && { tokenInvalidatedAt: new Date() }), + }, }); // Update roles if provided @@ -338,12 +364,22 @@ async function setUserDeveloperAccess(userId: number, enabled: boolean) { await prisma.userRole.create({ data: { userId, roleId: developerRole.id }, }); + // Token invalidieren bei Rechteänderung + await prisma.user.update({ + where: { id: userId }, + data: { tokenInvalidatedAt: new Date() }, + }); } else if (!enabled && hasRole) { // Remove Developer role console.log('Removing Developer role'); await prisma.userRole.delete({ where: { userId_roleId: { userId, roleId: developerRole.id } }, }); + // Token invalidieren bei Rechteänderung + await prisma.user.update({ + where: { id: userId }, + data: { tokenInvalidatedAt: new Date() }, + }); } else { console.log('No action needed - enabled:', enabled, 'hasRole:', !!hasRole); } diff --git a/backend/src/types/index.ts b/backend/src/types/index.ts index 53dd15e7..e5d4d2b8 100644 --- a/backend/src/types/index.ts +++ b/backend/src/types/index.ts @@ -7,6 +7,7 @@ export interface JwtPayload { customerId?: number; // Eigene Kunden-ID (bei Kundenportal-Login) isCustomerPortal?: boolean; // Ist dies ein Kundenportal-Login? representedCustomerIds?: number[]; // IDs der Kunden, die dieser Kunde vertreten kann + iat?: number; // Token ausgestellt am (Unix Timestamp, automatisch von JWT) } export interface AuthRequest extends Request { diff --git a/backend/src/utils/passwordGenerator.ts b/backend/src/utils/passwordGenerator.ts new file mode 100644 index 00000000..3364ab3a --- /dev/null +++ b/backend/src/utils/passwordGenerator.ts @@ -0,0 +1,101 @@ +// ==================== PASSWORD GENERATOR ==================== +// Generiert sichere, zufällige Passwörter + +import { randomBytes } from 'crypto'; + +// Zeichensätze für Passwort-Generierung +const LOWERCASE = 'abcdefghijklmnopqrstuvwxyz'; +const UPPERCASE = 'ABCDEFGHIJKLMNOPQRSTUVWXYZ'; +const NUMBERS = '0123456789'; +const SPECIAL = '!@#$%^&*()_+-=[]{}|;:,.<>?'; + +// Standard-Passwortlänge +const DEFAULT_LENGTH = 16; + +export interface PasswordOptions { + length?: number; + includeLowercase?: boolean; + includeUppercase?: boolean; + includeNumbers?: boolean; + includeSpecial?: boolean; +} + +/** + * Generiert ein kryptografisch sicheres Passwort + */ +export function generateSecurePassword(options: PasswordOptions = {}): string { + const { + length = DEFAULT_LENGTH, + includeLowercase = true, + includeUppercase = true, + includeNumbers = true, + includeSpecial = true, + } = options; + + // Zeichensatz zusammenstellen + let charset = ''; + const requiredChars: string[] = []; + + if (includeLowercase) { + charset += LOWERCASE; + requiredChars.push(getRandomChar(LOWERCASE)); + } + if (includeUppercase) { + charset += UPPERCASE; + requiredChars.push(getRandomChar(UPPERCASE)); + } + if (includeNumbers) { + charset += NUMBERS; + requiredChars.push(getRandomChar(NUMBERS)); + } + if (includeSpecial) { + charset += SPECIAL; + requiredChars.push(getRandomChar(SPECIAL)); + } + + if (charset.length === 0) { + throw new Error('Mindestens ein Zeichensatz muss aktiviert sein'); + } + + // Restliche Zeichen auffüllen + const remainingLength = Math.max(0, length - requiredChars.length); + const randomChars: string[] = []; + + for (let i = 0; i < remainingLength; i++) { + randomChars.push(getRandomChar(charset)); + } + + // Alle Zeichen mischen (Fisher-Yates Shuffle) + const allChars = [...requiredChars, ...randomChars]; + for (let i = allChars.length - 1; i > 0; i--) { + const j = getRandomInt(i + 1); + [allChars[i], allChars[j]] = [allChars[j], allChars[i]]; + } + + return allChars.join(''); +} + +/** + * Generiert ein einfaches Passwort ohne Sonderzeichen (für APIs die das nicht mögen) + */ +export function generateSimplePassword(length = 12): string { + return generateSecurePassword({ + length, + includeLowercase: true, + includeUppercase: true, + includeNumbers: true, + includeSpecial: false, + }); +} + +// Kryptografisch sichere Zufallszahl +function getRandomInt(max: number): number { + const bytes = randomBytes(4); + const value = bytes.readUInt32BE(0); + return value % max; +} + +// Zufälliges Zeichen aus einem Zeichensatz +function getRandomChar(charset: string): string { + return charset[getRandomInt(charset.length)]; +} diff --git a/backend/uploads/bank-cards/1768955872666-860459988.pdf b/backend/uploads/bank-cards/1768955872666-860459988.pdf deleted file mode 100644 index 5d3ae9e882c16413e3bb646ca303ebd6df9b006e..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 3009784 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