feat: prisma schema and voucher status

This commit is contained in:
opencode committed 2026-10-18 10:27:31 +02:00
1 parent 5ba920eb11
commit 159b549bf7
4 files changed
+82

No files matched your search

+6
View File
@@ -0,0 +1,6 @@
import { PrismaClient } from "@prisma/client";
const g = globalThis as unknown as { prisma?: PrismaClient };
export function getDb(): PrismaClient {
if (!g.prisma) g.prisma = new PrismaClient();
return g.prisma;
}
+6
View File
@@ -0,0 +1,6 @@
export type VoucherStatus = "aktiv" | "eingeloest" | "abgelaufen";
export function getVoucherStatus(v: { status: string; ablaufdatum: Date | null }): VoucherStatus {
if (v.status === "eingeloest") return "eingeloest";
if (v.ablaufdatum && v.ablaufdatum < new Date(new Date().toDateString())) return "abgelaufen";
return "aktiv";
}
+57
View File
@@ -0,0 +1,57 @@
datasource db {
provider = "sqlite"
url = env("DATABASE_URL")
}
generator client {
provider = "prisma-client-js"
}
model Voucher {
id Int @id @default(autoincrement())
name String
anbieter String
wertCents Int
restCents Int
ablaufdatum DateTime?
codeText String?
kategorie String?
notiz String?
status String @default("aktiv")
contacts VoucherContact[]
rules ReminderRule[]
createdAt DateTime @default(now())
updatedAt DateTime @updatedAt
}
model Contact {
id Int @id @default(autoincrement())
name String
email String?
telegramChatId String?
vouchers VoucherContact[]
}
model VoucherContact {
voucherId Int
contactId Int
voucher Voucher @relation(fields: [voucherId], references: [id], onDelete: Cascade)
contact Contact @relation(fields: [contactId], references: [id], onDelete: Cascade)
@@id([voucherId, contactId])
}
model ReminderRule {
id Int @id @default(autoincrement())
voucherId Int
tageVorher Int
voucher Voucher @relation(fields: [voucherId], references: [id], onDelete: Cascade)
logs NotificationLog[]
@@unique([voucherId, tageVorher])
}
model NotificationLog {
id Int @id @default(autoincrement())
ruleId Int
kanal String
empfaenger String
zielDatum String
status String
fehler String?
sentAt DateTime @default(now())
rule ReminderRule @relation(fields: [ruleId], references: [id], onDelete: Cascade)
@@unique([ruleId, kanal, empfaenger, zielDatum])
}
+13
View File
@@ -0,0 +1,13 @@
import { describe, it, expect } from "vitest";
import { getVoucherStatus } from "../lib/voucher-status";
describe("getVoucherStatus", () => {
it("eingeloest bleibt eingelöst auch wenn abgelaufen", () => {
expect(getVoucherStatus({ status: "eingeloest", ablaufdatum: new Date("2020-01-01") })).toBe("eingeloest");
});
it("ohne Ablaufdatum bleibt aktiv", () => {
expect(getVoucherStatus({ status: "aktiv", ablaufdatum: null })).toBe("aktiv");
});
it("vergangenes Datum wird abgelaufen", () => {
expect(getVoucherStatus({ status: "aktiv", ablaufdatum: new Date("2020-01-01") })).toBe("abgelaufen");
});
});