Skip to content
Merged

Dev #412

Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
@@ -0,0 +1,35 @@
-- Einmal nutzbare Nachmeldelinks für Anmeldungen außerhalb des Anmeldezeitraums.
-- CreateTable
CREATE TABLE "late_registration_link" (
"id" TEXT NOT NULL,
"courseId" TEXT NOT NULL,
"tokenHash" TEXT NOT NULL,
"note" TEXT,
"expiresAt" TIMESTAMP(3) NOT NULL,
"createdById" TEXT,
"createdAt" TIMESTAMP(3) NOT NULL DEFAULT CURRENT_TIMESTAMP,
"usedAt" TIMESTAMP(3),
"registrationId" TEXT,
"revokedAt" TIMESTAMP(3),

CONSTRAINT "late_registration_link_pkey" PRIMARY KEY ("id")
);

-- CreateIndex
CREATE UNIQUE INDEX "late_registration_link_tokenHash_key" ON "late_registration_link"("tokenHash");

-- CreateIndex
CREATE UNIQUE INDEX "late_registration_link_registrationId_key" ON "late_registration_link"("registrationId");

-- CreateIndex
CREATE INDEX "late_registration_link_courseId_idx" ON "late_registration_link"("courseId");

-- AddForeignKey
ALTER TABLE "late_registration_link" ADD CONSTRAINT "late_registration_link_courseId_fkey" FOREIGN KEY ("courseId") REFERENCES "Course"("id") ON DELETE CASCADE ON UPDATE CASCADE;

-- AddForeignKey
ALTER TABLE "late_registration_link" ADD CONSTRAINT "late_registration_link_createdById_fkey" FOREIGN KEY ("createdById") REFERENCES "user"("id") ON DELETE SET NULL ON UPDATE CASCADE;

-- AddForeignKey
ALTER TABLE "late_registration_link" ADD CONSTRAINT "late_registration_link_registrationId_fkey" FOREIGN KEY ("registrationId") REFERENCES "CourseRegistration"("id") ON DELETE SET NULL ON UPDATE CASCADE;

109 changes: 77 additions & 32 deletions prisma/schema.prisma
Original file line number Diff line number Diff line change
Expand Up @@ -33,25 +33,26 @@ model User {
bio String?
preferences Json?

accounts Account[]
sessions Session[]
twoFactor TwoFactor? @relation("UserTwoFactor")
bezirk Bezirk? @relation("BezirkUsers", fields: [bezirkId], references: [id], onDelete: SetNull)
uploadedMedia Media[] @relation("MediaUploadedBy")
uploadedDownloads Download[] @relation("DownloadUploadedBy")
posaunenwart Posaunenwart? @relation("PosaunenwartUser")
createdEvents Event[] @relation("EventCreator")
createdCourses Course[] @relation("CourseCreator")
createdPosts Post[] @relation("PostCreator")
authoredPosts Post[] @relation("PostAuthor")
reviewedEvents Event[] @relation("EventReviewer")
reviewedCourses Course[] @relation("CourseReviewer")
reviewedPosts Post[] @relation("PostReviewer")
courseCollaborations CourseCollaborator[]
sentCourseMails CourseMail[] @relation("CourseMailSender")
conductedEnsembles Ensemble[] @relation("EnsembleConductor")
representedEnsembles Ensemble[] @relation("EnsembleRepresentative")
conductedAuswahlChors AuswahlChor[] @relation("AuswahlChorConductor")
accounts Account[]
sessions Session[]
twoFactor TwoFactor? @relation("UserTwoFactor")
bezirk Bezirk? @relation("BezirkUsers", fields: [bezirkId], references: [id], onDelete: SetNull)
uploadedMedia Media[] @relation("MediaUploadedBy")
uploadedDownloads Download[] @relation("DownloadUploadedBy")
posaunenwart Posaunenwart? @relation("PosaunenwartUser")
createdEvents Event[] @relation("EventCreator")
createdCourses Course[] @relation("CourseCreator")
createdLateRegistrationLinks LateRegistrationLink[] @relation("LateRegistrationLinkCreator")
createdPosts Post[] @relation("PostCreator")
authoredPosts Post[] @relation("PostAuthor")
reviewedEvents Event[] @relation("EventReviewer")
reviewedCourses Course[] @relation("CourseReviewer")
reviewedPosts Post[] @relation("PostReviewer")
courseCollaborations CourseCollaborator[]
sentCourseMails CourseMail[] @relation("CourseMailSender")
conductedEnsembles Ensemble[] @relation("EnsembleConductor")
representedEnsembles Ensemble[] @relation("EnsembleRepresentative")
conductedAuswahlChors AuswahlChor[] @relation("AuswahlChorConductor")

bezirkPersons BezirkPerson[] @relation("BezirkPersonUser")
teamMember TeamMember? @relation("TeamMemberUser")
Expand Down Expand Up @@ -121,7 +122,6 @@ model GameResult {
@@map("game_result")
}


/**
* Custom Role model for flexible role-based permissions
* Separate from the UserRole enum to allow custom roles
Expand Down Expand Up @@ -470,7 +470,6 @@ model TwoFactor {
@@map("twoFactor")
}


enum EventEnsembleType {
AUSWAHLCHOR
ENSEMBLE
Expand Down Expand Up @@ -570,7 +569,9 @@ enum DownPaymentMode {
TICKET
}

/** Welcher Hinweis zur Erstattung bei der Anmeldung bestätigt werden muss. */
/**
* Welcher Hinweis zur Erstattung bei der Anmeldung bestätigt werden muss.
*/
enum DownPaymentRefundPolicy {
NON_REFUNDABLE
REFUNDABLE
Expand Down Expand Up @@ -649,7 +650,6 @@ enum ContentStatus {
ARCHIVED // No longer active
}


model Event {
id String @id @default(uuid())
/**
Expand Down Expand Up @@ -811,10 +811,14 @@ model Course {
* Bei TICKET trägt jede Preiskategorie ihren eigenen Betrag.
*/
downPaymentMode DownPaymentMode @default(NONE)
/** Betrag pro Teilnehmer bei DownPaymentMode.COURSE. */
/**
* Betrag pro Teilnehmer bei DownPaymentMode.COURSE.
*/
downPaymentAmount Float?
downPaymentRefundPolicy DownPaymentRefundPolicy @default(NON_REFUNDABLE)
/** Eigener Erstattungshinweis bei DownPaymentRefundPolicy.CUSTOM. */
/**
* Eigener Erstattungshinweis bei DownPaymentRefundPolicy.CUSTOM.
*/
downPaymentRefundText String?

prerequisites String?
Expand All @@ -833,6 +837,8 @@ model Course {
mails CourseMail[]
invoices Invoice[]

lateRegistrationLinks LateRegistrationLink[]

createdById String?
createdBy User? @relation("CourseCreator", fields: [createdById], references: [id], onDelete: SetNull)
reviewerId String?
Expand Down Expand Up @@ -993,14 +999,20 @@ model CourseRegistration {
* üblichen Regeln zum Bearbeiten und Stornieren.
*/
downPaymentAmount Float?
/** null genau dann, wenn downPaymentAmount null ist. */
/**
* null genau dann, wenn downPaymentAmount null ist.
*/
downPaymentStatus DownPaymentStatus?
downPaymentPaidAt DateTime?
/** Tatsächlich eingegangener Betrag; null heißt "voller Betrag" (wie Invoice.paidAmount). */
/**
* Tatsächlich eingegangener Betrag; null heißt "voller Betrag" (wie Invoice.paidAmount).
*/
downPaymentPaidAmount Float?
downPaymentPaidById String?
downPaymentPaidBy User? @relation("DownPaymentBooker", fields: [downPaymentPaidById], references: [id], onDelete: SetNull)
/** Interner Vermerk (Kontoauszug, Absprache mit der Kasse zur Erstattung). */
/**
* Interner Vermerk (Kontoauszug, Absprache mit der Kasse zur Erstattung).
*/
downPaymentNote String?

invoiceGenerated Boolean @default(false)
Expand All @@ -1022,17 +1034,23 @@ model CourseRegistration {
* Anmeldenden, wer nachrückt — so lange hält die Warteliste an.
*/
promotionOfferExpiresAt DateTime?
/** Wann das Kursteam an das auslaufende Angebot erinnert wurde. */
/**
* Wann das Kursteam an das auslaufende Angebot erinnert wurde.
*/
promotionOfferReminderSentAt DateTime?
/**
* Angebot abgelehnt oder verfallen, als so viele Plätze nutzbar waren: bis
* mehr frei werden, gehen sie an die Nächsten auf der Warteliste.
*/
promotionOfferPassedSeats Int?

participants Participant[]
invoices Invoice[]
registrant User? @relation(fields: [registrantId], references: [id], onDelete: SetNull)
participants Participant[]
invoices Invoice[]
registrant User? @relation(fields: [registrantId], references: [id], onDelete: SetNull)
/**
* Nachmeldelink, über den die Anmeldung nach der Frist kam.
*/
lateRegistrationLink LateRegistrationLink?

notes String?
createdAt DateTime @default(now())
Expand All @@ -1046,6 +1064,33 @@ model CourseRegistration {
@@index([promotionOfferExpiresAt])
}

/// Einmal nutzbarer Link, mit dem sich jemand außerhalb des Anmeldezeitraums
/// (meist nach der Frist) über das öffentliche Formular anmelden kann. Kapazität,
/// Preise und Pflichtfelder gelten wie sonst; nur die Zeit-Sperren entfallen.
model LateRegistrationLink {
id String @id @default(uuid())
courseId String
course Course @relation(fields: [courseId], references: [id], onDelete: Cascade)

/// SHA-256 des Tokens im Link. Der Token selbst wird nur einmal beim Erstellen gezeigt.
tokenHash String @unique
/// Interne Notiz, für wen der Link gedacht ist.
note String?
expiresAt DateTime

createdById String?
createdBy User? @relation("LateRegistrationLinkCreator", fields: [createdById], references: [id], onDelete: SetNull)
createdAt DateTime @default(now())

usedAt DateTime?
registrationId String? @unique
registration CourseRegistration? @relation(fields: [registrationId], references: [id], onDelete: SetNull)
revokedAt DateTime?

@@index([courseId])
@@map("late_registration_link")
}

/// Archived e-mail from an organizer to a course's registrants. Recipient addresses are
/// deliberately not stored, only the count, so registrant data isn't duplicated.
model CourseMail {
Expand Down
Loading
Loading