airbnb-finder/prisma/schema.prisma

153 lines
4.7 KiB
Plaintext

// This is your Prisma schema file
// Learn more: https://pris.ly/d/prisma-schema
generator client {
provider = "prisma-client-js"
}
datasource db {
provider = "sqlite"
url = env("DATABASE_URL")
}
// ============================================
// MODELS
// ============================================
model Listing {
id String @id @default(cuid())
slug String @unique
airbnbUrl String @unique @map("airbnb_url")
normalizedUrl String @unique @map("normalized_url")
externalId String? @unique @map("external_id")
// Basic Info
title String
locationText String? @map("location_text")
latitude Float?
longitude Float?
// Pricing
nightlyPrice Float? @map("nightly_price")
totalPrice Float? @map("total_price")
currency String? @default("EUR")
// Rating
rating Float?
reviewCount Int? @map("review_count")
// Capacity
guestCount Int? @map("guest_count")
officialGuestCount Int? @map("official_guest_count")
maxSleepingPlaces Int? @map("max_sleeping_places")
suitableFor4 Boolean? @map("suitable_for_4")
extraMattressesNeededFor4 Int? @map("extra_mattresses_needed_for_4")
bedTypesSummary String? @map("bed_types_summary")
// Room Details
bedrooms Int?
beds Int?
bathrooms Float?
// Description
description String?
hostName String? @map("host_name")
cancellationPolicy String? @map("cancellation_policy")
// Amenities (stored as JSON string)
amenities String? @map("amenities")
// Status & Flags (using String instead of Enum for SQLite)
isFavorite Boolean @default(false) @map("is_favorite")
status String @default("NEW") // NEW, INTERESTING, SHORTLIST, BOOKED, REJECTED
// Images
coverImage String? @map("cover_image")
// Raw Data
rawSourceData String? @map("raw_source_data")
// Timestamps
importedAt DateTime @default(now()) @map("imported_at")
updatedAt DateTime @updatedAt @map("updated_at")
// Relations
images ListingImage[]
notes AdminNote[]
sleepingOptions ListingSleepingOption[]
tags ListingTag[]
// Indexes
@@index([status])
@@index([isFavorite])
@@index([locationText])
@@index([nightlyPrice])
@@index([rating])
@@map("listings")
}
model ListingImage {
id String @id @default(cuid())
listingId String @map("listing_id")
url String
alt String?
sortOrder Int @default(0) @map("sort_order")
isExternal Boolean @default(true) @map("is_external")
createdAt DateTime @default(now()) @map("created_at")
listing Listing @relation(fields: [listingId], references: [id], onDelete: Cascade)
@@index([listingId, sortOrder])
@@map("listing_images")
}
model AdminNote {
id String @id @default(cuid())
listingId String @map("listing_id")
body String
createdAt DateTime @default(now()) @map("created_at")
updatedAt DateTime @updatedAt @map("updated_at")
listing Listing @relation(fields: [listingId], references: [id], onDelete: Cascade)
@@index([listingId, createdAt])
@@map("admin_notes")
}
model Tag {
id String @id @default(cuid())
name String @unique
slug String @unique
color String? @default("#6366f1")
listings ListingTag[]
@@map("tags")
}
model ListingTag {
listingId String @map("listing_id")
tagId String @map("tag_id")
listing Listing @relation(fields: [listingId], references: [id], onDelete: Cascade)
tag Tag @relation(fields: [tagId], references: [id], onDelete: Cascade)
@@id([listingId, tagId])
@@map("listing_tags")
}
model ListingSleepingOption {
id String @id @default(cuid())
listingId String @map("listing_id")
bedType String @map("bed_type") // DOUBLE, SINGLE, SOFA_BED, etc.
quantity Int @default(1)
spotsPerUnit Int @default(1) @map("spots_per_unit")
quality String @default("FULL") // FULL, AUXILIARY
label String?
notes String?
listing Listing @relation(fields: [listingId], references: [id], onDelete: Cascade)
@@index([listingId])
@@map("listing_sleeping_options")
}