feat: set up database / orm #25

Closed
opened 2025-05-04 16:19:40 +00:00 by lima · 2 comments
Member
https://www.prisma.io/docs/getting-started https://authjs.dev/getting-started/adapters/prisma#schema https://www.prisma.io/docs/getting-started/quickstart-sqlite
lima changed title from feat: set up database to feat: set up database / orm 2025-05-04 16:19:52 +00:00
lima added this to the MeetUp project 2025-05-04 23:35:46 +00:00
Author
Member
// Use DBML to define your database structure
// Docs: https://dbml.dbdiagram.io/docs

Project ScheduleApp {
  database_type: 'PostgreSQL'
  Note: 'Schema supporting users (Auth.js style), SSO via accounts table, friendships, groups, meetings, notifications (in-app & email), recurrence, and iCal import/export. All IDs (like CUIDs) are varchar. Optimized for dbdiagram.io free tier.'
}

// --- ENUM Definitions ---
enum participant_status {
  PENDING
  ACCEPTED
  DECLINED
  TENTATIVE
}

enum meeting_status {
  TENTATIVE
  CONFIRMED
  CANCELLED
}

enum friendship_status {
  PENDING
  ACCEPTED
  DECLINED
  BLOCKED
}

enum notification_type {
  FRIEND_REQUEST
  FRIEND_ACCEPT
  MEETING_INVITE
  MEETING_UPDATE
  MEETING_CANCEL
  MEETING_REMINDER
  GROUP_MEMBER_ADDED
  CALENDAR_SYNC_ERROR
}

enum group_member_role {
  ADMIN
  MEMBER
}

enum calendar_export_scope {
  MEETINGS_ONLY
  MEETINGS_AND_BLOCKED
  BLOCKED_ONLY
}

enum email_queue_status {
  PENDING
  PROCESSING
  SENT
  FAILED
  CANCELLED
}

// --- Authentication Tables (Auth.js Style) ---

Table users { // Mapped from Prisma 'User' model
  id varchar(50) [pk, not null, note: 'Primary key, CUID']
  username varchar(100) [unique, not null]
  first_name varchar(255) [note: 'User first name']
  last_name varchar(255) [note: 'User last name']
  email varchar(255) [unique, not null]
  email_verified timestamptz [note: 'Timestamp of email verification']
  password_hash varchar(255) [note: 'Nullable for SSO users, or if password login is separate']
  image text [note: 'URL to user image/avatar']
  timezone varchar(100) [not null, default: 'UTC', note: 'User preferred timezone']
  created_at timestamptz [not null, default: `now()`]
  updated_at timestamptz [not null, default: `now()`] // In Prisma, @updatedAt handles this automatically

  Note: 'Stores user account information, compatible with Auth.js User model.'
}

Table accounts { // Mapped from Prisma 'Account' model (for OAuth providers)
  provider varchar(255) [pk, not null, note: 'e.g., google, github']
  provider_account_id varchar(255) [pk, not null, note: 'User ID from the provider']
  user_id varchar(50) [not null, ref: > users.id, note: 'References users.id']
  type varchar(255) [not null, note: 'Provider type, e.g., oauth, oidc, email']
  refresh_token text
  access_token text
  expires_at integer
  token_type varchar(255)
  scope text
  id_token text
  session_state text
  created_at timestamptz [not null, default: `now()`]
  updated_at timestamptz [not null, default: `now()`]

  Note: 'Stores linked OAuth accounts for users, compatible with Auth.js Account model. Replaces user_sso_identities.'
}

Table sessions { // Mapped from Prisma 'Session' model
  session_token varchar(255) [pk, unique, not null] // Changed to PK
  user_id varchar(50) [not null, ref: > users.id]
  expires timestamptz [not null]
  created_at timestamptz [not null, default: `now()`]
  updated_at timestamptz [not null, default: `now()`]

  Note: 'Stores user sessions, compatible with Auth.js Session model.'
}

Table verification_tokens { // Mapped from Prisma 'VerificationToken' model
  identifier varchar(255) [pk, not null]
  token text [pk, unique, not null] // Changed to PK component and text
  expires timestamptz [not null]

  Note: 'For email verification, password reset, etc., compatible with Auth.js.'
}

Table authenticators { // Mapped from Prisma 'Authenticator' model (for WebAuthn)
  user_id varchar(50) [pk, not null, ref: > users.id]
  credential_id text [pk, unique, not null] // Changed to PK component and text
  provider_account_id text [not null, note: 'Usually links to an Account providerAccountId']
  credential_public_key text [not null]
  counter integer [not null]
  credential_device_type varchar(255) [not null]
  credential_backed_up boolean [not null]
  transports text

  Note: 'Stores WebAuthn authenticators, compatible with Auth.js.'
}


// --- Application Specific Tables (Adjusted for String User IDs) ---

Table friendships {
  user_id_1 varchar(50) [pk, not null, ref: > users.id, note: 'References users.id']
  user_id_2 varchar(50) [pk, not null, ref: > users.id, note: 'References users.id']
  status friendship_status [not null, default: 'PENDING']
  requested_at timestamptz [not null, default: `now()`]
  accepted_at timestamptz

  indexes {
    (user_id_2, status) [name: 'idx_friendships_user2_status']
  }
  Note: 'Stores friendship connections. Ensure application logic maintains user_id_1 < user_id_2 or handles pairs consistently.'
}

Table groups {
  id varchar(50) [pk, not null, note: 'Primary key, CUID']
  name varchar(255) [not null]
  description text
  creator_id varchar(50) [not null, ref: > users.id, note: 'User who created the group, references users.id']
  created_at timestamptz [not null, default: `now()`]
  updated_at timestamptz [not null, default: `now()`]

  indexes {
    (creator_id)
  }
  Note: 'Defines user-created groups.'
}

Table group_members {
  group_id varchar(50) [pk, not null, ref: > groups.id, note: 'References groups.id']
  user_id varchar(50) [pk, not null, ref: > users.id, note: 'References users.id']
  role group_member_role [not null, default: 'MEMBER', note: 'Role of the user within the group']
  added_at timestamptz [not null, default: `now()`]

  indexes {
    (user_id)
  }
  Note: 'Links users to groups (many-to-many). Composite PK (group_id, user_id).'
}

Table blocked_slots {
  id varchar(50) [pk, not null, note: 'Primary key, CUID']
  user_id varchar(50) [not null, ref: > users.id, note: 'References users.id']
  start_time timestamptz [not null, note: 'For recurring slots, this is the start time of the *first* occurrence.']
  end_time timestamptz [not null, note: 'For recurring slots, this is the end time of the *first* occurrence.']
  reason varchar(255)
  is_recurring boolean [not null, default: false, note: 'True if this slot follows a recurrence rule.']
  rrule varchar(255) [note: 'Recurrence rule string (iCalendar RRULE format). Null if not recurring.']
  recurrence_end_date date [note: 'Optional date when the recurrence stops. Null if it repeats indefinitely or is not recurring.']
  created_at timestamptz [not null, default: `now()`]
  updated_at timestamptz [not null, default: `now()`]

  indexes {
    (user_id, start_time, end_time)
    (user_id, is_recurring)
  }
  Note: 'User unavailability periods created within the app. Check constraint: end_time > start_time.'
}

Table meetings {
  id varchar(50) [pk, not null, note: 'Primary key, CUID']
  title varchar(255) [not null]
  description text
  start_time timestamptz [not null]
  end_time timestamptz [not null]
  organizer_id varchar(50) [not null, ref: > users.id, note: 'The user who created/organized the meeting, references users.id']
  location varchar(255)
  status meeting_status [not null, default: 'CONFIRMED']
  created_at timestamptz [not null, default: `now()`]
  updated_at timestamptz [not null, default: `now()`]

  indexes {
    (start_time, end_time)
    (organizer_id)
    (status)
  }
  Note: 'Scheduled events created within the app. Check constraint: end_time > start_time.'
}

Table meeting_participants {
  meeting_id varchar(50) [pk, not null, ref: > meetings.id, note: 'References meetings.id']
  user_id varchar(50) [pk, not null, ref: > users.id, note: 'References users.id']
  status participant_status [not null, default: 'PENDING']
  added_at timestamptz [not null, default: `now()`]

  indexes {
    (user_id, status) [name: 'idx_participants_user_status']
  }
  Note: 'Links users to meetings and tracks their invitation status.'
}

Table notifications {
  id varchar(50) [pk, not null, note: 'Primary key, CUID']
  user_id varchar(50) [not null, ref: > users.id, note: 'The recipient of the notification, references users.id']
  type notification_type [not null]
  related_entity_type varchar(50) [note: 'e.g., user, meeting, friendship, group, calendar_subscription']
  related_entity_id varchar(50) [note: 'ID of the related entity (e.g., user_id, meeting_id as CUIDs)']
  message text [not null, note: 'The content of the in-app notification']
  is_read boolean [not null, default: false]
  created_at timestamptz [not null, default: `now()`]

  indexes {
    (user_id, is_read, created_at) [name: 'idx_notifications_user_read_time']
  }
  Note: 'Stores in-app notifications for users. Email notifications are handled separately.'
}

Table user_notification_preferences {
  user_id varchar(50) [pk, not null, ref: > users.id, note: 'References users.id']
  notification_type notification_type [pk, not null, note: 'The type of notification.']
  email_enabled boolean [not null, default: false, note: 'If true, user wants email for this type of notification.']
  updated_at timestamptz [not null, default: `now()`]

  Note: 'Stores user preferences for receiving email notifications. Composite PK (user_id, notification_type).'
}

Table email_queue {
  id varchar(50) [pk, not null, note: 'Primary key, CUID']
  user_id varchar(50) [not null, ref: > users.id, note: 'The recipient user, references users.id']
  subject varchar(255) [not null, note: 'The subject line of the email.']
  body_html text [not null, note: 'Rendered HTML content of the email.']
  body_text text [note: 'Plain text version of the email.']
  status email_queue_status [not null, default: 'PENDING', note: 'Current status of this email in the queue.']
  scheduled_at timestamptz [not null, default: `now()`]
  attempts integer [not null, default: 0, note: 'Number of send attempts.']
  last_attempt_at timestamptz [note: 'Timestamp of the last send attempt.']
  sent_at timestamptz [note: 'Timestamp when successfully sent.']
  error_message text [note: 'Error message if the last send attempt failed.']
  created_at timestamptz [not null, default: `now()`]
  updated_at timestamptz [not null, default: `now()`]

  indexes {
    (status, scheduled_at) [name: 'idx_email_queue_pending_jobs']
    (user_id, created_at) [name: 'idx_email_queue_user_history']
  }
  Note: 'Queue for emails to be sent. Processed by a background worker.'
}

Table calendar_export_tokens {
  id varchar(50) [pk, not null, note: 'Primary key, CUID']
  user_id varchar(50) [not null, ref: > users.id, note: 'References users.id']
  token text [unique, not null, note: 'Secure, unique token for the feed URL']
  scope calendar_export_scope [not null, default: 'MEETINGS_ONLY', note: 'Defines what data is included.']
  is_active boolean [not null, default: true, note: 'Allows users to revoke access.']
  created_at timestamptz [not null, default: `now()`]
  last_accessed_at timestamptz [note: 'Timestamp of the last token use.']

  indexes {
    (user_id)
    (token) [unique] // Already unique by definition but good for explicit indexing
  }
  Note: 'Manages secure tokens for exporting user schedules via iCal URLs.'
}

Table calendar_subscriptions {
  id varchar(50) [pk, not null, note: 'Primary key, CUID']
  user_id varchar(50) [not null, ref: > users.id, note: 'References users.id']
  feed_url text [not null, note: 'URL of the external .ics feed']
  name varchar(255) [note: 'User-defined name for this subscription']
  color varchar(7) [note: 'Optional hex color code for UI display (e.g., #FF5733)']
  is_enabled boolean [not null, default: true, note: 'Whether sync is active.']
  last_synced_at timestamptz [note: 'Timestamp of the last successful sync.']
  last_sync_error text [note: 'Error message from the last failed sync.']
  sync_frequency_minutes integer [default: 60, note: 'How often to attempt sync.']
  created_at timestamptz [not null, default: `now()`]
  updated_at timestamptz [not null, default: `now()`]

  indexes {
    (user_id, is_enabled)
  }
  Note: 'Stores external iCal feeds a user subscribes to within the app.'
}

Table external_events {
  id varchar(50) [pk, not null, note: 'Primary key, CUID']
  subscription_id varchar(50) [not null, ref: > calendar_subscriptions.id, note: 'References calendar_subscriptions.id']
  ical_uid text [not null, note: 'Unique ID (UID) from the iCal event data.']
  summary text [note: 'Event title/summary from iCal.']
  description text [note: 'Event description from iCal.']
  start_time timestamptz [not null]
  end_time timestamptz [not null]
  is_all_day boolean [not null, default: false]
  location text [note: 'Event location from iCal.']
  rrule text [note: 'Recurrence rule string from iCal.']
  dtstamp timestamptz [note: 'DTSTAMP from iCal.']
  sequence integer [note: 'SEQUENCE from iCal for updates.']
  show_as_free boolean [not null, default: false, note: 'User override: if true, event does not block availability.']
  last_fetched_at timestamptz [not null, default: `now()`]

  indexes {
    (subscription_id, ical_uid) [unique, name: 'uq_external_event_sub_uid']
    (subscription_id, start_time, end_time)
    (subscription_id, show_as_free)
  }
  Note: 'Stores event occurrences from external iCal feeds. Needs background job for syncing.'
}
``` // Use DBML to define your database structure // Docs: https://dbml.dbdiagram.io/docs Project ScheduleApp { database_type: 'PostgreSQL' Note: 'Schema supporting users (Auth.js style), SSO via accounts table, friendships, groups, meetings, notifications (in-app & email), recurrence, and iCal import/export. All IDs (like CUIDs) are varchar. Optimized for dbdiagram.io free tier.' } // --- ENUM Definitions --- enum participant_status { PENDING ACCEPTED DECLINED TENTATIVE } enum meeting_status { TENTATIVE CONFIRMED CANCELLED } enum friendship_status { PENDING ACCEPTED DECLINED BLOCKED } enum notification_type { FRIEND_REQUEST FRIEND_ACCEPT MEETING_INVITE MEETING_UPDATE MEETING_CANCEL MEETING_REMINDER GROUP_MEMBER_ADDED CALENDAR_SYNC_ERROR } enum group_member_role { ADMIN MEMBER } enum calendar_export_scope { MEETINGS_ONLY MEETINGS_AND_BLOCKED BLOCKED_ONLY } enum email_queue_status { PENDING PROCESSING SENT FAILED CANCELLED } // --- Authentication Tables (Auth.js Style) --- Table users { // Mapped from Prisma 'User' model id varchar(50) [pk, not null, note: 'Primary key, CUID'] username varchar(100) [unique, not null] first_name varchar(255) [note: 'User first name'] last_name varchar(255) [note: 'User last name'] email varchar(255) [unique, not null] email_verified timestamptz [note: 'Timestamp of email verification'] password_hash varchar(255) [note: 'Nullable for SSO users, or if password login is separate'] image text [note: 'URL to user image/avatar'] timezone varchar(100) [not null, default: 'UTC', note: 'User preferred timezone'] created_at timestamptz [not null, default: `now()`] updated_at timestamptz [not null, default: `now()`] // In Prisma, @updatedAt handles this automatically Note: 'Stores user account information, compatible with Auth.js User model.' } Table accounts { // Mapped from Prisma 'Account' model (for OAuth providers) provider varchar(255) [pk, not null, note: 'e.g., google, github'] provider_account_id varchar(255) [pk, not null, note: 'User ID from the provider'] user_id varchar(50) [not null, ref: > users.id, note: 'References users.id'] type varchar(255) [not null, note: 'Provider type, e.g., oauth, oidc, email'] refresh_token text access_token text expires_at integer token_type varchar(255) scope text id_token text session_state text created_at timestamptz [not null, default: `now()`] updated_at timestamptz [not null, default: `now()`] Note: 'Stores linked OAuth accounts for users, compatible with Auth.js Account model. Replaces user_sso_identities.' } Table sessions { // Mapped from Prisma 'Session' model session_token varchar(255) [pk, unique, not null] // Changed to PK user_id varchar(50) [not null, ref: > users.id] expires timestamptz [not null] created_at timestamptz [not null, default: `now()`] updated_at timestamptz [not null, default: `now()`] Note: 'Stores user sessions, compatible with Auth.js Session model.' } Table verification_tokens { // Mapped from Prisma 'VerificationToken' model identifier varchar(255) [pk, not null] token text [pk, unique, not null] // Changed to PK component and text expires timestamptz [not null] Note: 'For email verification, password reset, etc., compatible with Auth.js.' } Table authenticators { // Mapped from Prisma 'Authenticator' model (for WebAuthn) user_id varchar(50) [pk, not null, ref: > users.id] credential_id text [pk, unique, not null] // Changed to PK component and text provider_account_id text [not null, note: 'Usually links to an Account providerAccountId'] credential_public_key text [not null] counter integer [not null] credential_device_type varchar(255) [not null] credential_backed_up boolean [not null] transports text Note: 'Stores WebAuthn authenticators, compatible with Auth.js.' } // --- Application Specific Tables (Adjusted for String User IDs) --- Table friendships { user_id_1 varchar(50) [pk, not null, ref: > users.id, note: 'References users.id'] user_id_2 varchar(50) [pk, not null, ref: > users.id, note: 'References users.id'] status friendship_status [not null, default: 'PENDING'] requested_at timestamptz [not null, default: `now()`] accepted_at timestamptz indexes { (user_id_2, status) [name: 'idx_friendships_user2_status'] } Note: 'Stores friendship connections. Ensure application logic maintains user_id_1 < user_id_2 or handles pairs consistently.' } Table groups { id varchar(50) [pk, not null, note: 'Primary key, CUID'] name varchar(255) [not null] description text creator_id varchar(50) [not null, ref: > users.id, note: 'User who created the group, references users.id'] created_at timestamptz [not null, default: `now()`] updated_at timestamptz [not null, default: `now()`] indexes { (creator_id) } Note: 'Defines user-created groups.' } Table group_members { group_id varchar(50) [pk, not null, ref: > groups.id, note: 'References groups.id'] user_id varchar(50) [pk, not null, ref: > users.id, note: 'References users.id'] role group_member_role [not null, default: 'MEMBER', note: 'Role of the user within the group'] added_at timestamptz [not null, default: `now()`] indexes { (user_id) } Note: 'Links users to groups (many-to-many). Composite PK (group_id, user_id).' } Table blocked_slots { id varchar(50) [pk, not null, note: 'Primary key, CUID'] user_id varchar(50) [not null, ref: > users.id, note: 'References users.id'] start_time timestamptz [not null, note: 'For recurring slots, this is the start time of the *first* occurrence.'] end_time timestamptz [not null, note: 'For recurring slots, this is the end time of the *first* occurrence.'] reason varchar(255) is_recurring boolean [not null, default: false, note: 'True if this slot follows a recurrence rule.'] rrule varchar(255) [note: 'Recurrence rule string (iCalendar RRULE format). Null if not recurring.'] recurrence_end_date date [note: 'Optional date when the recurrence stops. Null if it repeats indefinitely or is not recurring.'] created_at timestamptz [not null, default: `now()`] updated_at timestamptz [not null, default: `now()`] indexes { (user_id, start_time, end_time) (user_id, is_recurring) } Note: 'User unavailability periods created within the app. Check constraint: end_time > start_time.' } Table meetings { id varchar(50) [pk, not null, note: 'Primary key, CUID'] title varchar(255) [not null] description text start_time timestamptz [not null] end_time timestamptz [not null] organizer_id varchar(50) [not null, ref: > users.id, note: 'The user who created/organized the meeting, references users.id'] location varchar(255) status meeting_status [not null, default: 'CONFIRMED'] created_at timestamptz [not null, default: `now()`] updated_at timestamptz [not null, default: `now()`] indexes { (start_time, end_time) (organizer_id) (status) } Note: 'Scheduled events created within the app. Check constraint: end_time > start_time.' } Table meeting_participants { meeting_id varchar(50) [pk, not null, ref: > meetings.id, note: 'References meetings.id'] user_id varchar(50) [pk, not null, ref: > users.id, note: 'References users.id'] status participant_status [not null, default: 'PENDING'] added_at timestamptz [not null, default: `now()`] indexes { (user_id, status) [name: 'idx_participants_user_status'] } Note: 'Links users to meetings and tracks their invitation status.' } Table notifications { id varchar(50) [pk, not null, note: 'Primary key, CUID'] user_id varchar(50) [not null, ref: > users.id, note: 'The recipient of the notification, references users.id'] type notification_type [not null] related_entity_type varchar(50) [note: 'e.g., user, meeting, friendship, group, calendar_subscription'] related_entity_id varchar(50) [note: 'ID of the related entity (e.g., user_id, meeting_id as CUIDs)'] message text [not null, note: 'The content of the in-app notification'] is_read boolean [not null, default: false] created_at timestamptz [not null, default: `now()`] indexes { (user_id, is_read, created_at) [name: 'idx_notifications_user_read_time'] } Note: 'Stores in-app notifications for users. Email notifications are handled separately.' } Table user_notification_preferences { user_id varchar(50) [pk, not null, ref: > users.id, note: 'References users.id'] notification_type notification_type [pk, not null, note: 'The type of notification.'] email_enabled boolean [not null, default: false, note: 'If true, user wants email for this type of notification.'] updated_at timestamptz [not null, default: `now()`] Note: 'Stores user preferences for receiving email notifications. Composite PK (user_id, notification_type).' } Table email_queue { id varchar(50) [pk, not null, note: 'Primary key, CUID'] user_id varchar(50) [not null, ref: > users.id, note: 'The recipient user, references users.id'] subject varchar(255) [not null, note: 'The subject line of the email.'] body_html text [not null, note: 'Rendered HTML content of the email.'] body_text text [note: 'Plain text version of the email.'] status email_queue_status [not null, default: 'PENDING', note: 'Current status of this email in the queue.'] scheduled_at timestamptz [not null, default: `now()`] attempts integer [not null, default: 0, note: 'Number of send attempts.'] last_attempt_at timestamptz [note: 'Timestamp of the last send attempt.'] sent_at timestamptz [note: 'Timestamp when successfully sent.'] error_message text [note: 'Error message if the last send attempt failed.'] created_at timestamptz [not null, default: `now()`] updated_at timestamptz [not null, default: `now()`] indexes { (status, scheduled_at) [name: 'idx_email_queue_pending_jobs'] (user_id, created_at) [name: 'idx_email_queue_user_history'] } Note: 'Queue for emails to be sent. Processed by a background worker.' } Table calendar_export_tokens { id varchar(50) [pk, not null, note: 'Primary key, CUID'] user_id varchar(50) [not null, ref: > users.id, note: 'References users.id'] token text [unique, not null, note: 'Secure, unique token for the feed URL'] scope calendar_export_scope [not null, default: 'MEETINGS_ONLY', note: 'Defines what data is included.'] is_active boolean [not null, default: true, note: 'Allows users to revoke access.'] created_at timestamptz [not null, default: `now()`] last_accessed_at timestamptz [note: 'Timestamp of the last token use.'] indexes { (user_id) (token) [unique] // Already unique by definition but good for explicit indexing } Note: 'Manages secure tokens for exporting user schedules via iCal URLs.' } Table calendar_subscriptions { id varchar(50) [pk, not null, note: 'Primary key, CUID'] user_id varchar(50) [not null, ref: > users.id, note: 'References users.id'] feed_url text [not null, note: 'URL of the external .ics feed'] name varchar(255) [note: 'User-defined name for this subscription'] color varchar(7) [note: 'Optional hex color code for UI display (e.g., #FF5733)'] is_enabled boolean [not null, default: true, note: 'Whether sync is active.'] last_synced_at timestamptz [note: 'Timestamp of the last successful sync.'] last_sync_error text [note: 'Error message from the last failed sync.'] sync_frequency_minutes integer [default: 60, note: 'How often to attempt sync.'] created_at timestamptz [not null, default: `now()`] updated_at timestamptz [not null, default: `now()`] indexes { (user_id, is_enabled) } Note: 'Stores external iCal feeds a user subscribes to within the app.' } Table external_events { id varchar(50) [pk, not null, note: 'Primary key, CUID'] subscription_id varchar(50) [not null, ref: > calendar_subscriptions.id, note: 'References calendar_subscriptions.id'] ical_uid text [not null, note: 'Unique ID (UID) from the iCal event data.'] summary text [note: 'Event title/summary from iCal.'] description text [note: 'Event description from iCal.'] start_time timestamptz [not null] end_time timestamptz [not null] is_all_day boolean [not null, default: false] location text [note: 'Event location from iCal.'] rrule text [note: 'Recurrence rule string from iCal.'] dtstamp timestamptz [note: 'DTSTAMP from iCal.'] sequence integer [note: 'SEQUENCE from iCal for updates.'] show_as_free boolean [not null, default: false, note: 'User override: if true, event does not block availability.'] last_fetched_at timestamptz [not null, default: `now()`] indexes { (subscription_id, ical_uid) [unique, name: 'uq_external_event_sub_uid'] (subscription_id, start_time, end_time) (subscription_id, show_as_free) } Note: 'Stores event occurrences from external iCal feeds. Needs background job for syncing.' } ```
Author
Member

@micha.bok

Convert to Prisma Scheme

@micha.bok Convert to Prisma Scheme
micha.bok was assigned by lima 2025-05-07 09:33:06 +00:00
dominik self-assigned this 2025-05-12 11:34:48 +00:00
dominik removed their assignment 2025-05-12 19:09:38 +00:00
Sign in to join this conversation.
No project
No assignees
1 participant
Notifications
Due date
The due date is invalid or out of range. Please use the format "yyyy-mm-dd".

No due date set.

Blocks
Reference: DHBW-WE/MeetUp#25
No description provided.