feat: Datenmodell und Umgebung fuer Integrationen
Ein Zustand je Quelle haelt fest, wie weit gelesen wurde und ob es klappt. Der Merker ist bewusst ein freier Text: Zammad braucht darin einen Zeitstempel, Telegram den Zaehler der zuletzt geholten Nachricht. Dazu die gespiegelte Belegung ohne Titel, das Adressbuch der erlaubten Telegram-Chats und der Einmalcode, mit dem sich ein Chat anmeldet. Welche Integration eine Instanz darf, entscheidet weiterhin INSTANZ. Ein Zammad-Token in der Instanz daheim bleibt wirkungslos — das steht in den Faehigkeiten, nicht in einer Einstellung, die sich verstellen liesse. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
This commit is contained in:
co-authored by
Claude Opus 5
parent
ab1b898e44
commit
7f8f505126
@@ -0,0 +1,62 @@
|
||||
-- AlterTable
|
||||
ALTER TABLE "aufgabe" ADD COLUMN "spiegeln" BOOLEAN NOT NULL DEFAULT false;
|
||||
|
||||
-- AlterTable
|
||||
ALTER TABLE "benachrichtigungseinstellung" ADD COLUMN "perTelegram" BOOLEAN NOT NULL DEFAULT false;
|
||||
|
||||
-- CreateTable
|
||||
CREATE TABLE "integrationszustand" (
|
||||
"id" TEXT NOT NULL,
|
||||
"quelle" "Quelle" NOT NULL,
|
||||
"merker" TEXT,
|
||||
"letzterLauf" TIMESTAMP(3),
|
||||
"letzterErfolg" TIMESTAMP(3),
|
||||
"letzterFehler" TEXT,
|
||||
"fehlversuche" INTEGER NOT NULL DEFAULT 0,
|
||||
"erstelltAm" TIMESTAMP(3) NOT NULL DEFAULT CURRENT_TIMESTAMP,
|
||||
"aktualisiertAm" TIMESTAMP(3) NOT NULL,
|
||||
|
||||
CONSTRAINT "integrationszustand_pkey" PRIMARY KEY ("id")
|
||||
);
|
||||
|
||||
-- CreateTable
|
||||
CREATE TABLE "spiegelbelegung" (
|
||||
"id" TEXT NOT NULL,
|
||||
"quelleRef" TEXT NOT NULL,
|
||||
"beginn" TIMESTAMP(3) NOT NULL,
|
||||
"ende" TIMESTAMP(3) NOT NULL,
|
||||
"empfangenAm" TIMESTAMP(3) NOT NULL DEFAULT CURRENT_TIMESTAMP,
|
||||
|
||||
CONSTRAINT "spiegelbelegung_pkey" PRIMARY KEY ("id")
|
||||
);
|
||||
|
||||
-- CreateTable
|
||||
CREATE TABLE "telegram_chat" (
|
||||
"id" TEXT NOT NULL,
|
||||
"chatId" BIGINT NOT NULL,
|
||||
"bezeichnung" TEXT,
|
||||
"benutzerId" TEXT,
|
||||
"meldungen" BOOLEAN NOT NULL DEFAULT true,
|
||||
"erstelltAm" TIMESTAMP(3) NOT NULL DEFAULT CURRENT_TIMESTAMP,
|
||||
"zuletztBenutzt" TIMESTAMP(3),
|
||||
|
||||
CONSTRAINT "telegram_chat_pkey" PRIMARY KEY ("id")
|
||||
);
|
||||
|
||||
-- CreateIndex
|
||||
CREATE UNIQUE INDEX "integrationszustand_quelle_key" ON "integrationszustand"("quelle");
|
||||
|
||||
-- CreateIndex
|
||||
CREATE UNIQUE INDEX "spiegelbelegung_quelleRef_key" ON "spiegelbelegung"("quelleRef");
|
||||
|
||||
-- CreateIndex
|
||||
CREATE INDEX "spiegelbelegung_beginn_idx" ON "spiegelbelegung"("beginn");
|
||||
|
||||
-- CreateIndex
|
||||
CREATE UNIQUE INDEX "telegram_chat_chatId_key" ON "telegram_chat"("chatId");
|
||||
|
||||
-- CreateIndex
|
||||
CREATE INDEX "telegram_chat_benutzerId_idx" ON "telegram_chat"("benutzerId");
|
||||
|
||||
-- AddForeignKey
|
||||
ALTER TABLE "telegram_chat" ADD CONSTRAINT "telegram_chat_benutzerId_fkey" FOREIGN KEY ("benutzerId") REFERENCES "benutzer"("id") ON DELETE SET NULL ON UPDATE CASCADE;
|
||||
@@ -0,0 +1,16 @@
|
||||
-- CreateTable
|
||||
CREATE TABLE "telegram_kopplung" (
|
||||
"id" TEXT NOT NULL,
|
||||
"code" TEXT NOT NULL,
|
||||
"benutzerId" TEXT NOT NULL,
|
||||
"gueltigBis" TIMESTAMP(3) NOT NULL,
|
||||
"erstelltAm" TIMESTAMP(3) NOT NULL DEFAULT CURRENT_TIMESTAMP,
|
||||
|
||||
CONSTRAINT "telegram_kopplung_pkey" PRIMARY KEY ("id")
|
||||
);
|
||||
|
||||
-- CreateIndex
|
||||
CREATE UNIQUE INDEX "telegram_kopplung_code_key" ON "telegram_kopplung"("code");
|
||||
|
||||
-- CreateIndex
|
||||
CREATE INDEX "telegram_kopplung_gueltigBis_idx" ON "telegram_kopplung"("gueltigBis");
|
||||
+93
-3
@@ -38,6 +38,7 @@ model Benutzer {
|
||||
benachrichtigung Benachrichtigungseinstellung?
|
||||
pushGeraete PushGeraet[]
|
||||
meldungen Meldungsnachweis[]
|
||||
telegramChats TelegramChat[]
|
||||
|
||||
@@index([aktiv])
|
||||
@@map("benutzer")
|
||||
@@ -222,6 +223,10 @@ model Aufgabe {
|
||||
/// Kennung beim Ursprungssystem, z. B. die Ticketnummer.
|
||||
quelleRef String?
|
||||
|
||||
/// Ausdruecklich zum Spiegeln freigegeben. Nur was hier true ist, verlaesst
|
||||
/// die Instanz mit Titel – alles andere bleibt, wo es ist.
|
||||
spiegeln Boolean @default(false)
|
||||
|
||||
erstelltAm DateTime @default(now())
|
||||
aktualisiertAm DateTime @updatedAt
|
||||
|
||||
@@ -391,9 +396,10 @@ model Benachrichtigungseinstellung {
|
||||
benutzerId String @unique
|
||||
|
||||
/// Kommagetrennte Anlaesse, siehe src/lib/benachrichtigung.ts.
|
||||
anlaesse String @default("tagesueberblick,faelligkeit")
|
||||
perPush Boolean @default(false)
|
||||
perMail Boolean @default(false)
|
||||
anlaesse String @default("tagesueberblick,faelligkeit")
|
||||
perPush Boolean @default(false)
|
||||
perMail Boolean @default(false)
|
||||
perTelegram Boolean @default(false)
|
||||
|
||||
/// Alles als Minuten seit Mitternacht, Europe/Berlin.
|
||||
ueberblickUm Int @default(420)
|
||||
@@ -448,3 +454,87 @@ model Meldungsnachweis {
|
||||
@@index([gesendetAm])
|
||||
@@map("meldungsnachweis")
|
||||
}
|
||||
|
||||
/// Zustand einer Integration: wie weit sie gelesen hat und ob es klappt.
|
||||
///
|
||||
/// Eine Zeile je Quelle. Der Merker ist bewusst ein freier Text – jede
|
||||
/// Integration legt darin ab, was sie zum Fortsetzen braucht: Zammad einen
|
||||
/// Zeitstempel, Telegram den Zaehler der zuletzt geholten Nachricht.
|
||||
model Integrationszustand {
|
||||
id String @id @default(cuid())
|
||||
quelle Quelle @unique
|
||||
|
||||
/// Woher es weitergeht. Bedeutung haengt an der Quelle.
|
||||
merker String?
|
||||
|
||||
letzterLauf DateTime?
|
||||
letzterErfolg DateTime?
|
||||
letzterFehler String?
|
||||
/// Fehlschlaege in Folge; bei Erfolg wieder null.
|
||||
fehlversuche Int @default(0)
|
||||
|
||||
erstelltAm DateTime @default(now())
|
||||
aktualisiertAm DateTime @updatedAt
|
||||
|
||||
@@map("integrationszustand")
|
||||
}
|
||||
|
||||
/// Dienstliche Belegung, die aus der anderen Instanz kommt.
|
||||
///
|
||||
/// Bewusst ohne Titel: Daheim soll sehen, *dass* die Zeit weg ist, nicht
|
||||
/// woran gearbeitet wird. Firmeninhalte verlassen die Firma nicht.
|
||||
model Spiegelbelegung {
|
||||
id String @id @default(cuid())
|
||||
|
||||
/// Kennung des Zeitblocks in der sendenden Instanz.
|
||||
quelleRef String @unique
|
||||
|
||||
beginn DateTime
|
||||
ende DateTime
|
||||
|
||||
empfangenAm DateTime @default(now())
|
||||
|
||||
@@index([beginn])
|
||||
@@map("spiegelbelegung")
|
||||
}
|
||||
|
||||
/// Ein Telegram-Chat, der mit dem Planer reden darf.
|
||||
///
|
||||
/// Wer nicht hier steht, wird verworfen – ein Bot-Token laesst sich erraten
|
||||
/// oder abgreifen, die Chatkennung ist der zweite Riegel.
|
||||
model TelegramChat {
|
||||
id String @id @default(cuid())
|
||||
/// Chatkennung bei Telegram; kann negativ sein (Gruppen).
|
||||
chatId BigInt @unique
|
||||
|
||||
bezeichnung String?
|
||||
benutzerId String?
|
||||
|
||||
/// Empfaengt dieser Chat auch Meldungen, nicht nur Aufgaben?
|
||||
meldungen Boolean @default(true)
|
||||
|
||||
erstelltAm DateTime @default(now())
|
||||
zuletztBenutzt DateTime?
|
||||
|
||||
benutzer Benutzer? @relation(fields: [benutzerId], references: [id], onDelete: SetNull)
|
||||
|
||||
@@index([benutzerId])
|
||||
@@map("telegram_chat")
|
||||
}
|
||||
|
||||
/// Einmalcode, mit dem sich ein Telegram-Chat anmeldet.
|
||||
///
|
||||
/// Ohne ihn muesste die Chatkennung von Hand eingetragen werden – und um sie
|
||||
/// zu erfahren, muesste der Planer auf Nachrichten Unbekannter antworten.
|
||||
/// Genau das soll er nicht.
|
||||
model TelegramKopplung {
|
||||
id String @id @default(cuid())
|
||||
code String @unique
|
||||
benutzerId String
|
||||
gueltigBis DateTime
|
||||
|
||||
erstelltAm DateTime @default(now())
|
||||
|
||||
@@index([gueltigBis])
|
||||
@@map("telegram_kopplung")
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user