Files

416 lines
17 KiB
Plaintext
Raw Permalink Normal View History

generator client {
provider = "prisma-client-js"
}
datasource db {
provider = "postgresql"
}
model Church {
id String @id @default(uuid())
name String
address String?
city String?
state String?
zip String?
country String @default("US")
latitude Float
longitude Float
phone String?
website String?
massScheduleUrl String? @map("mass_schedule_url")
email String?
pastorName String? @map("pastor_name")
diocese String?
directions String?
wheelchairAccess Boolean @default(false) @map("wheelchair_access")
masstimesId String? @unique @map("masstimes_id")
source String @default("masstimes") // "osm", "masstimes", "manual"
osmId String? @unique @map("osm_id") // OpenStreetMap node/way/relation ID (e.g. "node/12345")
baiduId String? @unique @map("baidu_id") // Baidu Maps POI uid
hasWebsite Boolean @default(false) @map("has_website")
osmLastSyncedAt DateTime? @map("osm_last_synced_at") // Last time this church was synced from OSM
baiduLastSyncedAt DateTime? @map("baidu_last_synced_at") // Last time this church was synced from Baidu Maps
googlePlaceId String? @unique @map("google_place_id")
orarimesseId String? @unique @map("orarimesse_id")
orarimesseLastSyncedAt DateTime? @map("orarimesse_last_synced_at")
massSchedulesPhId String? @unique @map("mass_schedules_ph_id")
philmassId String? @unique @map("philmass_id")
horariosMisasId String? @unique @map("horarios_misas_id")
mszeInfoId String? @unique @map("msze_info_id")
weekdayMassesId String? @unique @map("weekday_masses_id")
messesInfoId String? @unique @map("messes_info_id")
bohosluzbyId String? @unique @map("bohosluzby_id")
miserendId String? @unique @map("miserend_id")
discovermassId String? @unique @map("discovermass_id")
gottesdienstzeitenId String? @unique @map("gottesdienstzeiten_id")
kerknetId String? @unique @map("kerknet_id")
buscarmisasNetworkId String? @unique @map("buscarmisas_network_id")
2026-04-12 23:49:08 -04:00
gcatholicId String? @unique @map("gcatholic_id")
claimed Boolean @default(false)
claimedAt DateTime? @map("claimed_at")
lastScrapedAt DateTime? @map("last_scraped_at")
scrapeStrategy String @default("generic") @map("scrape_strategy")
cityNormalized String? @map("city_normalized")
lastTransferredAt DateTime? @map("last_transferred_at") // Last time this church was transferred to Neon production
freeSearchedAt DateTime? @map("free_searched_at") // Last time FreeSearch was used to find website
websiteLanguage String? @map("website_language") // ISO 639-1 language code detected from website
websiteType String? @map("website_type") // URL classification: parish, social_media, wiki, directory, umbrella, government, heritage, review, video, maps
reverseGeocodedAt DateTime? @map("reverse_geocoded_at") // When reverse geocoding was attempted
googleSearchedAt DateTime? @map("google_searched_at") // When Google Places enrichment was attempted
createdAt DateTime @default(now()) @map("created_at")
updatedAt DateTime @updatedAt @map("updated_at")
2026-04-28 18:04:02 -04:00
parochiaSlug String? @map("parochia_slug")
dioceseId String? @map("diocese_id")
claimedByUserId String? @map("claimed_by_user_id")
massSchedules MassSchedule[]
confessionSchedules ConfessionSchedule[]
adorationSchedules AdorationSchedule[]
specialServices SpecialService[]
scraperConfig ChurchScraperConfig?
dioceseObj Diocese? @relation(fields: [dioceseId], references: [id])
claimedByUser User? @relation(fields: [claimedByUserId], references: [id])
claimRequests ClaimRequest[]
@@index([osmId])
@@index([baiduId])
@@index([source])
@@index([hasWebsite])
@@index([state])
@@index([city])
@@index([state, cityNormalized])
@@index([country])
@@index([country, cityNormalized])
@@index([lastTransferredAt])
@@index([freeSearchedAt])
@@index([websiteLanguage])
@@index([websiteType])
@@index([orarimesseId])
@@index([massSchedulesPhId])
@@index([philmassId])
@@index([horariosMisasId])
@@index([mszeInfoId])
@@index([weekdayMassesId])
@@index([messesInfoId])
@@index([bohosluzbyId])
@@index([miserendId])
@@index([discovermassId])
@@index([gottesdienstzeitenId])
@@index([kerknetId])
@@index([buscarmisasNetworkId])
2026-04-12 23:49:08 -04:00
@@index([gcatholicId])
@@index([dioceseId])
@@index([claimedByUserId])
@@map("churches")
}
model MassSchedule {
id String @id @default(uuid())
churchId String @map("church_id")
dayOfWeek Int @map("day_of_week")
time String // Store as HH:MM string
massType String? @map("mass_type")
language String @default("English")
notes String?
isActive Boolean @default(true) @map("is_active")
createdByUserId String? @map("created_by_user_id")
createdAt DateTime @default(now()) @map("created_at")
updatedAt DateTime @updatedAt @map("updated_at")
church Church @relation(fields: [churchId], references: [id], onDelete: Cascade)
createdBy User? @relation("MassScheduleCreator", fields: [createdByUserId], references: [id])
@@index([churchId, dayOfWeek, isActive])
@@index([churchId, isActive])
@@map("mass_schedules")
}
model ConfessionSchedule {
id String @id @default(uuid())
churchId String @map("church_id")
dayOfWeek Int @map("day_of_week")
startTime String @map("start_time")
endTime String @map("end_time")
notes String?
isActive Boolean @default(true) @map("is_active")
createdByUserId String? @map("created_by_user_id")
createdAt DateTime @default(now()) @map("created_at")
updatedAt DateTime @updatedAt @map("updated_at")
church Church @relation(fields: [churchId], references: [id], onDelete: Cascade)
createdBy User? @relation("ConfessionScheduleCreator", fields: [createdByUserId], references: [id])
@@index([churchId, dayOfWeek, isActive])
@@index([churchId, isActive])
@@map("confession_schedules")
}
model AdorationSchedule {
id String @id @default(uuid())
churchId String @map("church_id")
dayOfWeek Int @map("day_of_week")
startTime String @map("start_time")
endTime String @map("end_time")
isPerpetual Boolean @default(false) @map("is_perpetual")
notes String?
isActive Boolean @default(true) @map("is_active")
createdByUserId String? @map("created_by_user_id")
createdAt DateTime @default(now()) @map("created_at")
updatedAt DateTime @updatedAt @map("updated_at")
church Church @relation(fields: [churchId], references: [id], onDelete: Cascade)
createdBy User? @relation("AdorationScheduleCreator", fields: [createdByUserId], references: [id])
@@index([churchId, dayOfWeek, isActive])
@@index([churchId, isActive])
@@map("adoration_schedules")
}
model LiturgicalDay {
id String @id @default(uuid())
date DateTime @unique @db.Date
season String // "Ordinary Time", "Advent", "Lent", etc.
seasonWeek String? @map("season_week") // "23rd Week" etc.
liturgicalColor String? @map("liturgical_color") // "green", "violet", "white", "red"
feastName String? @map("feast_name") // Solemnity/feast name if applicable
feastRank String? @map("feast_rank") // "Solemnity", "Feast", "Memorial", "Optional Memorial"
firstReading String? @map("first_reading") // Citation: "Wisdom 9:13-18b"
psalm String? // "Psalm 90:3-4, 5-6, 12-13, 14 and 17"
secondReading String? @map("second_reading") // Citation (Sundays/Solemnities only)
gospel String? // Citation: "Luke 14:25-33"
firstReadingText String? @map("first_reading_text") // Full verse text from Bible API
psalmText String? @map("psalm_text") // Full verse text from Bible API
secondReadingText String? @map("second_reading_text") // Full verse text from Bible API
gospelText String? @map("gospel_text") // Full verse text from Bible API
usccbUrl String? @map("usccb_url") // Link to full text on USCCB
versesSource String? @map("verses_source") // 'bible_api' | 'youversion' | 'none'
versesCachedAt DateTime? @map("verses_cached_at") // When verses were last fetched
createdAt DateTime @default(now()) @map("created_at")
updatedAt DateTime @updatedAt @map("updated_at")
@@index([date])
@@index([season])
@@index([versesCachedAt])
@@map("liturgical_days")
}
model ChurchScraperConfig {
id String @id @default(uuid())
churchId String @unique @map("church_id")
strategyName String @map("strategy_name")
lastSuccessAt DateTime? @map("last_success_at")
lastFailureAt DateTime? @map("last_failure_at")
failureCount Int @default(0) @map("failure_count")
rawHtml String? @map("raw_html")
createdAt DateTime @default(now()) @map("created_at")
updatedAt DateTime @updatedAt @map("updated_at")
church Church @relation(fields: [churchId], references: [id], onDelete: Cascade)
@@map("church_scraper_config")
}
model User {
id String @id @default(uuid())
name String
email String @unique
emailVerified DateTime? @map("email_verified")
hashedPassword String? @map("hashed_password")
image String?
sortPreference String @default("time") @map("sort_preference")
languagePreference String? @map("language_preference")
lastLatitude Float? @map("last_latitude")
lastLongitude Float? @map("last_longitude")
lastLocationName String? @map("last_location_name")
createdAt DateTime @default(now()) @map("created_at")
updatedAt DateTime @updatedAt @map("updated_at")
suspended Boolean @default(false)
suspendedAt DateTime? @map("suspended_at")
accounts Account[]
sessions Session[]
claimedChurches Church[]
massSchedules MassSchedule[] @relation("MassScheduleCreator")
confessionSchedules ConfessionSchedule[] @relation("ConfessionScheduleCreator")
adorationSchedules AdorationSchedule[] @relation("AdorationScheduleCreator")
specialServices SpecialService[] @relation("SpecialServiceCreator")
claimRequestsSent ClaimRequest[] @relation("ClaimRequester")
claimRequestsReceived ClaimRequest[] @relation("ClaimRespondent")
@@map("users")
}
model Account {
id String @id @default(uuid())
userId String @map("user_id")
type String
provider String
providerAccountId String @map("provider_account_id")
refresh_token String?
access_token String?
expires_at Int?
token_type String?
scope String?
id_token String?
session_state String?
user User @relation(fields: [userId], references: [id], onDelete: Cascade)
@@unique([provider, providerAccountId])
@@map("accounts")
}
model Session {
id String @id @default(uuid())
sessionToken String @unique @map("session_token")
userId String @map("user_id")
expires DateTime
user User @relation(fields: [userId], references: [id], onDelete: Cascade)
@@map("sessions")
}
model ContactMessage {
id String @id @default(uuid())
name String?
email String?
message String?
wantsToDonate Boolean @default(false) @map("wants_to_donate")
showInDonorLog Boolean @default(false) @map("show_in_donor_log")
read Boolean @default(false)
createdAt DateTime @default(now()) @map("created_at")
updatedAt DateTime @updatedAt @map("updated_at")
@@index([read])
@@index([createdAt])
@@map("contact_messages")
}
model Donation {
id String @id @default(uuid())
displayName String? @map("display_name")
message String?
approved Boolean @default(false)
approvedAt DateTime? @map("approved_at")
createdAt DateTime @default(now()) @map("created_at")
updatedAt DateTime @updatedAt @map("updated_at")
@@index([approved])
@@index([createdAt])
@@map("donations")
}
model Diocese {
id String @id @default(uuid())
name String
country String
language String
website String?
directoryUrl String? @map("directory_url")
scrapeConfig Json? @map("scrape_config")
churchCount Int @default(0) @map("church_count")
lastScrapedAt DateTime? @map("last_scraped_at")
lastSuccessAt DateTime? @map("last_success_at")
lastFailureAt DateTime? @map("last_failure_at")
failureCount Int @default(0) @map("failure_count")
active Boolean @default(true)
notes String?
createdAt DateTime @default(now()) @map("created_at")
updatedAt DateTime @updatedAt @map("updated_at")
churches Church[]
@@unique([name, country])
@@index([country])
@@index([active])
@@index([lastScrapedAt])
@@map("dioceses")
}
model BackgroundJob {
id String @id @default(uuid())
type String // "scraper", "google-enrichment", "freesearch-enrichment"
language String? // "english", "french", "generic" (null for enrichment jobs)
status String @default("pending") // "pending", "running", "completed", "failed", "stopping"
totalItems Int @default(0) @map("total_items")
processed Int @default(0)
succeeded Int @default(0)
failed Int @default(0)
itemsFound Int @default(0) @map("items_found")
error String?
config Json?
startedAt DateTime? @map("started_at")
completedAt DateTime? @map("completed_at")
createdAt DateTime @default(now()) @map("created_at")
updatedAt DateTime @updatedAt @map("updated_at")
@@index([type])
@@index([status])
@@map("background_jobs")
}
model EmailVerification {
id String @id @default(uuid())
email String
code String // 6-digit code
expiresAt DateTime @map("expires_at")
attempts Int @default(0) // rate limit verification attempts
createdAt DateTime @default(now()) @map("created_at")
@@index([email])
@@index([expiresAt])
@@map("email_verifications")
}
model SpecialService {
id String @id @default(uuid())
churchId String @map("church_id")
serviceType String @map("service_type") // "stations_of_the_cross", "midnight_mass", "easter_vigil", etc.
customName String? @map("custom_name") // only when serviceType="other"
dayOfWeek Int? @map("day_of_week") // 0-6, null for date-specific
date DateTime? @db.Date // specific date for non-recurring
time String // HH:MM
endTime String? @map("end_time") // HH:MM, optional
recurrence String @default("weekly") // "weekly", "biweekly", "monthly", "annually", "once"
notes String?
isActive Boolean @default(true) @map("is_active")
createdByUserId String? @map("created_by_user_id")
createdAt DateTime @default(now()) @map("created_at")
updatedAt DateTime @updatedAt @map("updated_at")
church Church @relation(fields: [churchId], references: [id], onDelete: Cascade)
createdBy User? @relation("SpecialServiceCreator", fields: [createdByUserId], references: [id])
@@index([churchId, isActive])
@@index([churchId, serviceType])
@@map("special_services")
}
model ClaimRequest {
id String @id @default(uuid())
churchId String @map("church_id")
requesterUserId String @map("requester_user_id")
claimantUserId String @map("claimant_user_id")
message String
status String @default("pending") // pending, accepted, denied, ignored, auto_transferred
denyReason String? @map("deny_reason")
expiresAt DateTime @map("expires_at")
respondedAt DateTime? @map("responded_at")
createdAt DateTime @default(now()) @map("created_at")
updatedAt DateTime @updatedAt @map("updated_at")
church Church @relation(fields: [churchId], references: [id], onDelete: Cascade)
requester User @relation("ClaimRequester", fields: [requesterUserId], references: [id], onDelete: Cascade)
claimant User @relation("ClaimRespondent", fields: [claimantUserId], references: [id], onDelete: Cascade)
@@index([claimantUserId, status])
@@index([requesterUserId])
@@index([churchId])
@@index([expiresAt, status])
@@map("claim_requests")
}