413 lines
17 KiB
Plaintext
413 lines
17 KiB
Plaintext
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")
|
|
kerknetId String? @unique @map("kerknet_id")
|
|
gottesdienstzeitenId String? @unique @map("gottesdienstzeiten_id")
|
|
discovermassId String? @unique @map("discovermass_id")
|
|
buscarmisasNetworkId String? @unique @map("buscarmisas_network_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")
|
|
|
|
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([kerknetId])
|
|
@@index([gottesdienstzeitenId])
|
|
@@index([discovermassId])
|
|
@@index([buscarmisasNetworkId])
|
|
@@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")
|
|
}
|