lomavuokraus/prisma/seed.js
Tero Halla-aho 0bb709d9c5
Some checks failed
CI / checks (push) Has been cancelled
chore: fix audit alerts and formatting
2026-02-04 12:43:03 +02:00

873 lines
28 KiB
JavaScript

/* eslint-disable no-console */
const path = require("path");
const fs = require("fs");
require("dotenv").config({ path: path.join(__dirname, "..", ".env") });
if (fs.existsSync(path.join(__dirname, "..", "creds", ".env"))) {
require("dotenv").config({
path: path.join(__dirname, "..", "creds", ".env"),
});
}
const bcrypt = require("bcryptjs");
const {
PrismaClient,
Role,
UserStatus,
ListingStatus,
} = require("@prisma/client");
const { PrismaPg } = require("@prisma/adapter-pg");
const { Pool } = require("pg");
if (!process.env.DATABASE_URL) {
console.error("DATABASE_URL is not set; cannot seed.");
process.exit(1);
}
const prisma = new PrismaClient({
adapter: new PrismaPg(
new Pool({ connectionString: process.env.DATABASE_URL }),
),
});
const SAMPLE_SLUG = "saimaa-lakeside-cabin";
const DEFAULT_LOCALE = "en";
const SAMPLE_EMAIL = "host@lomavuokraus.fi";
const SAMPLE_IMAGE_DIR = path.join(__dirname, "..", "sampleimages");
function detectMimeType(fileName) {
const ext = path.extname(fileName).toLowerCase();
if (ext === ".png") return "image/png";
if (ext === ".webp") return "image/webp";
if (ext === ".gif") return "image/gif";
return "image/jpeg";
}
function loadSampleImage(fileName) {
if (!fileName) return null;
const filePath = path.join(SAMPLE_IMAGE_DIR, fileName);
if (!fs.existsSync(filePath)) {
console.warn(`Sample image missing: ${filePath}`);
return null;
}
const data = fs.readFileSync(filePath);
return {
data,
size: data.length,
mimeType: detectMimeType(fileName),
};
}
async function main() {
const adminEmail = process.env.ADMIN_EMAIL;
const adminPassword = process.env.ADMIN_INITIAL_PASSWORD;
function buildImageCreates(item) {
const results = [];
const coverFile = loadSampleImage(item.cover.file);
if (coverFile || item.cover.url) {
results.push({
data: coverFile?.data,
mimeType: coverFile?.mimeType || (item.cover.url ? null : undefined),
size: coverFile?.size ?? null,
url: coverFile ? null : (item.cover.url ?? null),
altText: item.cover.altText ?? null,
order: 1,
isCover: true,
});
}
item.images.forEach((img) => {
const file = loadSampleImage(img.file);
const hasSource = file || img.url;
if (!hasSource) return;
results.push({
data: file?.data,
mimeType: file?.mimeType || (img.url ? null : undefined),
size: file?.size ?? null,
url: file ? null : (img.url ?? null),
altText: img.altText ?? null,
order: results.length + 1,
isCover: false,
});
});
return results;
}
if (!adminEmail || !adminPassword) {
console.warn(
"ADMIN_EMAIL or ADMIN_INITIAL_PASSWORD missing; admin user will not be seeded.",
);
}
let adminUser = null;
if (adminEmail && adminPassword) {
const adminHash = await bcrypt.hash(adminPassword, 12);
adminUser = await prisma.user.upsert({
where: { email: adminEmail },
update: {
passwordHash: adminHash,
role: Role.ADMIN,
status: UserStatus.ACTIVE,
emailVerifiedAt: new Date(),
approvedAt: new Date(),
},
create: {
email: adminEmail,
passwordHash: adminHash,
role: Role.ADMIN,
status: UserStatus.ACTIVE,
emailVerifiedAt: new Date(),
approvedAt: new Date(),
},
});
}
const sampleHostHash = await bcrypt.hash("changeme-sample", 12);
const owner = await prisma.user.upsert({
where: { email: SAMPLE_EMAIL },
update: {
name: "Sample Host",
phone: "+358401234567",
role: "USER",
passwordHash: sampleHostHash,
status: UserStatus.ACTIVE,
emailVerifiedAt: new Date(),
approvedAt: new Date(),
},
create: {
email: SAMPLE_EMAIL,
name: "Sample Host",
phone: "+358401234567",
role: "USER",
passwordHash: sampleHostHash,
status: UserStatus.ACTIVE,
emailVerifiedAt: new Date(),
approvedAt: new Date(),
},
});
let listings = [
{
slug: SAMPLE_SLUG,
isSample: true,
city: "Punkaharju",
region: "South Karelia",
country: "Finland",
streetAddress: "Saimaan rantatie 12",
addressNote: "Lakeside trail, 5 min from main road",
latitude: 61.756,
longitude: 29.328,
maxGuests: 6,
bedrooms: 3,
beds: 4,
bathrooms: 1,
hasSauna: true,
hasFireplace: true,
hasWifi: true,
hasAirConditioning: false,
hasKitchen: true,
hasDishwasher: false,
hasWashingMachine: false,
hasBarbecue: false,
hasMicrowave: true,
hasFreeParking: true,
petsAllowed: false,
byTheLake: true,
evChargingAvailable: true,
hasSkiPass: false,
priceWeekdayEuros: 145,
priceWeekendEuros: 165,
cover: {
file: "saimaa-lakeside-cabin-cover.jpg",
url: "https://images.unsplash.com/photo-1505691938895-1758d7feb511?auto=format&fit=crop&w=1600&q=80",
altText: "Lakeside cabin with sauna",
},
images: [
{
file: "saimaa-lakeside-cabin-sauna.jpg",
url: "https://images.unsplash.com/photo-1505693416388-ac5ce068fe85?auto=format&fit=crop&w=1600&q=80",
altText: "Wood-fired sauna by the lake",
},
{
file: "saimaa-lakeside-cabin-lounge.jpg",
url: "https://images.unsplash.com/photo-1470246973918-29a93221c455?auto=format&fit=crop&w=1600&q=80",
altText: "Living area with fireplace",
},
],
titleEn: "Saimaa lakeside cabin with sauna",
teaserEn: "Sauna, lake view, private dock, and cozy fireplace.",
descEn:
"Classic timber cabin right on Lake Saimaa. Wood-fired sauna, private dock, and a short forest walk to the nearest village. Perfect for slow weekends and midsummer gatherings.",
titleFi: "Saimaan rantamökki saunalla",
teaserFi: "Puusauna, järvinäköala, oma laituri ja takka.",
descFi:
"Perinteinen hirsimökki Saimaan rannalla. Puusauna, oma laituri ja lyhyt metsäreitti kylään. Sopii täydellisesti viikonloppuihin ja juhannukseen.",
},
{
slug: "helsinki-design-loft",
isSample: true,
city: "Helsinki",
region: "Uusimaa",
country: "Finland",
streetAddress: "Katajanokanranta 4",
addressNote: "Buzz 12B, elevator to 5th floor",
latitude: 60.1675,
longitude: 24.9529,
maxGuests: 4,
bedrooms: 1,
beds: 2,
bathrooms: 1,
hasSauna: false,
hasFireplace: false,
hasWifi: true,
hasAirConditioning: true,
hasKitchen: true,
hasDishwasher: false,
hasWashingMachine: false,
hasBarbecue: false,
hasMicrowave: true,
hasFreeParking: false,
petsAllowed: false,
byTheLake: false,
evChargingAvailable: true,
hasSkiPass: false,
priceWeekdayEuros: 165,
priceWeekendEuros: 185,
cover: {
file: "helsinki-design-loft-cover.jpg",
url: "https://images.unsplash.com/photo-1505693415763-3bd1620f58c3?auto=format&fit=crop&w=1600&q=80",
altText: "Modern loft living room",
},
images: [
{
file: "helsinki-design-loft-balcony.jpg",
url: "https://images.unsplash.com/photo-1505691938895-1758d7feb511?auto=format&fit=crop&w=1600&q=80",
altText: "Balcony view",
},
{
file: "helsinki-design-loft-bedroom.jpg",
url: "https://images.unsplash.com/photo-1505691938895-1758d7feb511?auto=format&fit=crop&w=1600&q=80",
altText: "Cozy bedroom",
},
],
titleEn: "Helsinki design loft with AC",
teaserEn: "Top-floor loft, AC, fast Wi-Fi, tram at the door.",
descEn:
"Bright design loft near the harbor. Air conditioning, fiber Wi-Fi, and views over Katajanokka. Perfect city break base.",
titleFi: "Helsingin design-lofti ilmastoinnilla",
teaserFi: "Ylimmän kerroksen loft, ilmastointi ja nopea netti.",
descFi:
"Valoisa loft Katajanokalla. Ilmastointi, kuitunetti ja näkymä merelle. Täydellinen kaupunkiloma.",
},
{
slug: "turku-riverside-apartment",
isSample: true,
city: "Turku",
region: "Varsinais-Suomi",
country: "Finland",
streetAddress: "Läntinen Rantakatu 10",
addressNote: "Self check-in lockbox",
latitude: 60.4518,
longitude: 22.2666,
maxGuests: 3,
bedrooms: 1,
beds: 2,
bathrooms: 1,
hasSauna: false,
hasFireplace: false,
hasWifi: true,
hasAirConditioning: false,
hasKitchen: true,
hasDishwasher: false,
hasWashingMachine: false,
hasBarbecue: false,
hasMicrowave: true,
hasFreeParking: true,
petsAllowed: true,
byTheLake: false,
evChargingAvailable: false,
hasSkiPass: false,
priceWeekdayEuros: 110,
priceWeekendEuros: 125,
cover: {
file: "turku-riverside-apartment-cover.jpg",
url: "https://images.unsplash.com/photo-1522708323590-d24dbb6b0267?auto=format&fit=crop&w=1600&q=80",
altText: "Apartment living room",
},
images: [
{
file: "turku-riverside-apartment-kitchen.jpg",
url: "https://images.unsplash.com/photo-1505691938895-1758d7feb511?auto=format&fit=crop&w=1600&q=80",
altText: "Kitchen area",
},
],
titleEn: "Riverside apartment in Turku",
teaserEn: "By the Aura river, pet-friendly, cozy base.",
descEn:
"Compact one-bedroom next to the Aura river. Cafés outside, pet-friendly, fiber internet for workations.",
titleFi: "Aurajoen varrella, lemmikkiystävällinen",
teaserFi: "Aurajoen kupeessa, lemmikit sallittu.",
descFi:
"Kompakti yksiö Aurajoen varrella. Kahvilat vieressä, lemmikit sallittu, kuitunetti etätöihin.",
},
{
slug: "rovaniemi-aurora-cabin",
isSample: true,
city: "Rovaniemi",
region: "Lapland",
country: "Finland",
streetAddress: "Ounasjoenkuja 8",
addressNote: "Snow tires required in winter",
latitude: 66.5039,
longitude: 25.7294,
maxGuests: 5,
bedrooms: 2,
beds: 4,
bathrooms: 1,
hasSauna: true,
hasFireplace: true,
hasWifi: true,
hasAirConditioning: false,
hasKitchen: true,
hasDishwasher: false,
hasWashingMachine: false,
hasBarbecue: false,
hasMicrowave: false,
hasFreeParking: true,
petsAllowed: false,
byTheLake: true,
evChargingAvailable: true,
evChargingOnSite: true,
hasSkiPass: true,
priceWeekdayEuros: 189,
priceWeekendEuros: 215,
cover: {
file: "rovaniemi-aurora-cabin-cover.jpg",
url: "https://images.unsplash.com/photo-1505693416388-ac5ce068fe85?auto=format&fit=crop&w=1600&q=80",
altText: "Aurora cabin by the river",
},
images: [
{
file: "rovaniemi-aurora-cabin-lounge.jpg",
url: "https://images.unsplash.com/photo-1470246973918-29a93221c455?auto=format&fit=crop&w=1600&q=80",
altText: "Fireplace lounge",
},
],
titleEn: "Aurora riverside cabin",
teaserEn: "Sauna, fireplace, river views, EV charging.",
descEn:
"Timber cabin on the Ounasjoki riverside. Wood sauna, fireplace, glass lounge for auroras, free EV charging.",
titleFi: "Revontulikämppä joen rannalla",
teaserFi: "Sauna, takka, jokinäkymä ja ilmainen lataus.",
descFi:
"Hirsimökki Ounasjoen rannalla. Puusauna, takka ja lasikuisti revontulien katseluun, ilmainen sähköauton lataus.",
},
{
slug: "tampere-sauna-studio",
isSample: true,
city: "Tampere",
region: "Pirkanmaa",
country: "Finland",
streetAddress: "Hämeenkatu 25",
addressNote: "Key pickup from lobby",
latitude: 61.4981,
longitude: 23.7608,
maxGuests: 2,
bedrooms: 0,
beds: 1,
bathrooms: 1,
hasSauna: true,
hasFireplace: false,
hasWifi: true,
hasAirConditioning: true,
hasKitchen: true,
hasDishwasher: false,
hasWashingMachine: false,
hasBarbecue: false,
hasMicrowave: true,
hasFreeParking: false,
petsAllowed: false,
byTheLake: false,
evChargingAvailable: false,
hasSkiPass: false,
priceWeekdayEuros: 95,
priceWeekendEuros: 110,
cover: {
file: "tampere-sauna-studio-cover.jpg",
url: "https://images.unsplash.com/photo-1505691938895-1758d7feb511?auto=format&fit=crop&w=1600&q=80",
altText: "Studio interior",
},
images: [
{
file: "tampere-sauna-studio-sauna.jpg",
url: "https://images.unsplash.com/photo-1505691938895-1758d7feb511?auto=format&fit=crop&w=1600&q=80",
altText: "Private sauna",
},
],
titleEn: "Tampere studio with private sauna",
teaserEn: "City center, private sauna, AC and fiber.",
descEn:
"Compact studio on Hämeenkatu with private electric sauna, air conditioning, and fiber internet. Steps from tram.",
titleFi: "Tampereen keskustastudio saunalla",
teaserFi: "Yksityinen sauna, ilmastointi, kuitu.",
descFi:
"Kompakti studio Hämeenkadulla. Oma sähkösauna, ilmastointi ja kuitunetti. Ratikka vieressä.",
},
{
slug: "vaasa-seaside-villa",
isSample: true,
city: "Vaasa",
region: "Ostrobothnia",
country: "Finland",
streetAddress: "Rantakatu 3",
addressNote: "Parking for 3 cars",
latitude: 63.096,
longitude: 21.6158,
maxGuests: 8,
bedrooms: 4,
beds: 6,
bathrooms: 2,
hasSauna: true,
hasFireplace: true,
hasWifi: true,
hasAirConditioning: false,
hasKitchen: true,
hasDishwasher: false,
hasWashingMachine: false,
hasBarbecue: false,
hasMicrowave: true,
hasFreeParking: true,
petsAllowed: true,
byTheLake: true,
evChargingAvailable: true,
evChargingOnSite: true,
hasSkiPass: true,
priceWeekdayEuros: 245,
priceWeekendEuros: 275,
cover: {
file: "vaasa-seaside-villa-cover.jpg",
url: "https://images.unsplash.com/photo-1505691938895-1758d7feb511?auto=format&fit=crop&w=1600&q=80",
altText: "Seaside villa deck",
},
images: [
{
file: "vaasa-seaside-villa-lounge.jpg",
url: "https://images.unsplash.com/photo-1505691938895-1758d7feb511?auto=format&fit=crop&w=1600&q=80",
altText: "Seaside villa lounge",
},
],
titleEn: "Seaside villa in Vaasa",
teaserEn: "Deck, sauna, pet-friendly, paid EV charging.",
descEn:
"Spacious villa on the coast with large deck, wood sauna, fireplace lounge. Pets welcome; paid EV charger on site.",
titleFi: "Rantahuvila Vaasassa",
teaserFi: "Terassi, sauna, lemmikit ok, maksullinen lataus.",
descFi:
"Tilava huvila meren rannalla, iso terassi, puusauna ja takkahuone. Lemmikit sallittu; maksullinen latauspiste.",
},
{
slug: "kuopio-lakeside-apartment",
isSample: true,
city: "Kuopio",
region: "Northern Savonia",
country: "Finland",
streetAddress: "Satamakatu 7",
addressNote: "Underground parking",
latitude: 62.8924,
longitude: 27.6783,
maxGuests: 4,
bedrooms: 2,
beds: 3,
bathrooms: 1,
hasSauna: true,
hasFireplace: false,
hasWifi: true,
hasAirConditioning: false,
hasKitchen: true,
hasDishwasher: false,
hasWashingMachine: false,
hasBarbecue: false,
hasMicrowave: true,
hasFreeParking: true,
petsAllowed: false,
byTheLake: true,
evChargingAvailable: true,
evChargingOnSite: true,
hasSkiPass: true,
priceWeekdayEuros: 129,
priceWeekendEuros: 149,
cover: {
file: "kuopio-lakeside-apartment-cover.jpg",
url: "https://images.unsplash.com/photo-1470246973918-29a93221c455?auto=format&fit=crop&w=1600&q=80",
altText: "Lake view balcony",
},
images: [
{
file: "kuopio-lakeside-apartment-sauna.jpg",
url: "https://images.unsplash.com/photo-1470246973918-29a93221c455?auto=format&fit=crop&w=1600&q=80",
altText: "Apartment sauna",
},
],
titleEn: "Kuopio lakeside apartment with sauna",
teaserEn: "Balcony to Kallavesi, sauna, free EV charging.",
descEn:
"Two-bedroom apartment overlooking Lake Kallavesi. Glass balcony, electric sauna, underground parking with free EV charging.",
titleFi: "Kuopion järvinäkymä ja sauna",
teaserFi: "Parveke Kallavedelle, sauna, ilmainen lataus.",
descFi:
"Kaksio Kallaveden rannalla. Lasitettu parveke, sähkösauna, hallipaikka ja ilmainen sähköauton lataus.",
},
{
slug: "porvoo-river-loft",
isSample: true,
city: "Porvoo",
region: "Uusimaa",
country: "Finland",
streetAddress: "Mannerheiminkatu 12",
addressNote: "Historic building, stairs only",
latitude: 60.3943,
longitude: 25.6659,
maxGuests: 2,
bedrooms: 1,
beds: 1,
bathrooms: 1,
hasSauna: false,
hasFireplace: true,
hasWifi: true,
hasAirConditioning: false,
hasKitchen: true,
hasDishwasher: false,
hasWashingMachine: false,
hasBarbecue: false,
hasMicrowave: true,
hasFreeParking: false,
petsAllowed: false,
byTheLake: false,
evChargingAvailable: false,
hasSkiPass: false,
priceWeekdayEuros: 99,
priceWeekendEuros: 115,
cover: {
file: "porvoo-river-loft-cover.jpg",
url: "https://images.unsplash.com/photo-1505691938895-1758d7feb511?auto=format&fit=crop&w=1600&q=80",
altText: "Loft interior",
},
images: [
{
file: "porvoo-river-loft-fireplace.jpg",
url: "https://images.unsplash.com/photo-1505691938895-1758d7feb511?auto=format&fit=crop&w=1600&q=80",
altText: "Fireplace corner",
},
],
titleEn: "Porvoo old town river loft",
teaserEn: "Historic charm, fireplace, steps from river.",
descEn:
"Cozy loft in Porvoo old town. Brick walls, fireplace, and views toward the riverside warehouses.",
titleFi: "Porvoon jokilofti",
teaserFi: "Takka ja vanhan kaupungin tunnelma.",
descFi:
"Kotoisa loft Porvoon vanhassa kaupungissa. Tiiliseinät, takka ja näkymä jokirantaan.",
},
{
slug: "oulu-tech-apartment",
isSample: true,
city: "Oulu",
region: "Northern Ostrobothnia",
country: "Finland",
streetAddress: "Technopolis 2",
addressNote: "Smart lock entry",
latitude: 65.0121,
longitude: 25.4651,
maxGuests: 2,
bedrooms: 1,
beds: 1,
bathrooms: 1,
hasSauna: false,
hasFireplace: false,
hasWifi: true,
hasAirConditioning: true,
hasKitchen: true,
hasDishwasher: false,
hasWashingMachine: false,
hasBarbecue: false,
hasMicrowave: true,
hasFreeParking: true,
petsAllowed: false,
byTheLake: false,
evChargingAvailable: true,
evChargingOnSite: true,
priceWeekdayEuros: 105,
priceWeekendEuros: 120,
cover: {
file: "oulu-tech-apartment-cover.jpg",
url: "https://images.unsplash.com/photo-1522708323590-d24dbb6b0267?auto=format&fit=crop&w=1600&q=80",
altText: "Modern apartment",
},
images: [
{
file: "oulu-tech-apartment-desk.jpg",
url: "https://images.unsplash.com/photo-1522708323590-d24dbb6b0267?auto=format&fit=crop&w=1600&q=80",
altText: "Work desk in apartment",
},
],
titleEn: "Smart apartment in Oulu",
teaserEn: "AC, smart lock, free EV charging in garage.",
descEn:
"Modern one-bedroom near Technopolis. Air conditioning, smart lock, desk for work, garage with free EV chargers.",
titleFi: "Moderni Oulun yksiö",
teaserFi: "Ilmastointi, älylukko, ilmainen lataus.",
descFi:
"Moderni yksiö Technopoliksen lähellä. Ilmastointi, älylukko, työpiste ja ilmaiset latauspaikat hallissa.",
},
{
slug: "mariehamn-harbor-flat",
isSample: true,
city: "Mariehamn",
region: "Åland",
country: "Finland",
streetAddress: "Hamngatan 5",
addressNote: "Ferry terminal 10 min walk",
latitude: 60.0973,
longitude: 19.9348,
maxGuests: 3,
bedrooms: 1,
beds: 2,
bathrooms: 1,
hasSauna: false,
hasFireplace: false,
hasWifi: true,
hasAirConditioning: false,
hasKitchen: true,
hasDishwasher: false,
hasWashingMachine: false,
hasBarbecue: false,
hasMicrowave: true,
hasFreeParking: true,
petsAllowed: false,
byTheLake: true,
evChargingAvailable: true,
hasSkiPass: true,
priceWeekdayEuros: 115,
priceWeekendEuros: 130,
cover: {
file: "mariehamn-harbor-flat-cover.jpg",
url: "https://images.unsplash.com/photo-1470246973918-29a93221c455?auto=format&fit=crop&w=1600&q=80",
altText: "Harbor view",
},
images: [
{
file: "mariehamn-harbor-flat-living.jpg",
url: "https://images.unsplash.com/photo-1470246973918-29a93221c455?auto=format&fit=crop&w=1600&q=80",
altText: "Harbor-facing living room",
},
],
titleEn: "Harbor flat in Mariehamn",
teaserEn: "Walk to ferries, harbor views, paid EV nearby.",
descEn:
"Bright flat near the harbor. Walk to ferries and restaurants, harbor-facing balcony, paid EV charging at the public lot.",
titleFi: "Satamahuoneisto Maarianhaminassa",
teaserFi: "Satamanäkymä, kävely lautoille.",
descFi:
"Valoisa huoneisto sataman tuntumassa. Parveke satamaan, ravintolat lähellä, maksullinen lataus viereisellä parkkipaikalla.",
},
];
// Fill in any missing amenities/prices with reasonable defaults
const randBool = (p = 0.5) => Math.random() < p;
listings = listings.map((item) => {
const weekdayPrice =
item.priceWeekdayEuros ?? Math.round(Math.random() * (220 - 90) + 90);
const evChargingOnSite = item.evChargingOnSite ?? randBool(0.15);
const evChargingAvailable =
item.evChargingAvailable ?? evChargingOnSite ?? randBool(0.4);
return {
...item,
priceWeekdayEuros: weekdayPrice,
priceWeekendEuros:
item.priceWeekendEuros ?? (weekdayPrice ? weekdayPrice + 15 : null),
hasKitchen: item.hasKitchen ?? randBool(0.9),
hasDishwasher: item.hasDishwasher ?? randBool(0.6),
hasWashingMachine: item.hasWashingMachine ?? randBool(0.6),
hasBarbecue: item.hasBarbecue ?? randBool(0.5),
hasMicrowave: item.hasMicrowave ?? randBool(0.7),
hasFreeParking: item.hasFreeParking ?? randBool(0.6),
evChargingOnSite,
evChargingAvailable,
wheelchairAccessible: item.wheelchairAccessible ?? randBool(0.25),
hasSkiPass: item.hasSkiPass ?? randBool(0.2),
};
});
for (const item of listings) {
const existing = await prisma.listingTranslation.findFirst({
where: { slug: item.slug },
select: { listingId: true },
});
const imageCreates = buildImageCreates(item);
if (!existing) {
const created = await prisma.listing.create({
data: {
ownerId: owner.id,
status: ListingStatus.PUBLISHED,
approvedAt: new Date(),
approvedById: adminUser ? adminUser.id : owner.id,
isSample: item.isSample ?? false,
country: item.country,
region: item.region,
city: item.city,
streetAddress: item.streetAddress,
addressNote: item.addressNote,
latitude: item.latitude,
longitude: item.longitude,
maxGuests: item.maxGuests,
bedrooms: item.bedrooms,
beds: item.beds,
bathrooms: item.bathrooms,
hasSauna: item.hasSauna,
hasFireplace: item.hasFireplace,
hasWifi: item.hasWifi,
hasAirConditioning: item.hasAirConditioning,
hasKitchen: item.hasKitchen ?? false,
hasDishwasher: item.hasDishwasher ?? false,
hasWashingMachine: item.hasWashingMachine ?? false,
hasBarbecue: item.hasBarbecue ?? false,
hasMicrowave: item.hasMicrowave ?? false,
hasFreeParking: item.hasFreeParking ?? false,
petsAllowed: item.petsAllowed,
byTheLake: item.byTheLake,
evChargingAvailable:
item.evChargingAvailable ?? item.evChargingOnSite ?? false,
evChargingOnSite: item.evChargingOnSite ?? false,
wheelchairAccessible: item.wheelchairAccessible ?? false,
priceWeekdayEuros: item.priceWeekdayEuros,
priceWeekendEuros: item.priceWeekendEuros,
contactName: "Sample Host",
contactEmail: SAMPLE_EMAIL,
contactPhone: owner.phone,
published: true,
translations: {
createMany: {
data: [
{
locale: "en",
slug: item.slug,
title: item.titleEn,
teaser: item.teaserEn,
description: item.descEn,
},
{
locale: "fi",
slug: item.slug,
title: item.titleFi,
teaser: item.teaserFi,
description: item.descFi,
},
],
},
},
images: imageCreates.length ? { create: imageCreates } : undefined,
},
});
console.log("Seeded listing:", created.id, item.slug);
continue;
}
const listingId = existing.listingId;
await prisma.listing.update({
where: { id: listingId },
data: {
isSample: item.isSample ?? false,
country: item.country,
region: item.region,
city: item.city,
streetAddress: item.streetAddress,
addressNote: item.addressNote,
latitude: item.latitude,
longitude: item.longitude,
maxGuests: item.maxGuests,
bedrooms: item.bedrooms,
beds: item.beds,
bathrooms: item.bathrooms,
hasSauna: item.hasSauna,
hasFireplace: item.hasFireplace,
hasWifi: item.hasWifi,
hasAirConditioning: item.hasAirConditioning,
hasKitchen: item.hasKitchen ?? false,
hasDishwasher: item.hasDishwasher ?? false,
hasWashingMachine: item.hasWashingMachine ?? false,
hasBarbecue: item.hasBarbecue ?? false,
hasMicrowave: item.hasMicrowave ?? false,
hasFreeParking: item.hasFreeParking ?? false,
petsAllowed: item.petsAllowed,
byTheLake: item.byTheLake,
evChargingAvailable:
item.evChargingAvailable ?? item.evChargingOnSite ?? false,
evChargingOnSite: item.evChargingOnSite ?? false,
wheelchairAccessible: item.wheelchairAccessible ?? false,
priceWeekdayEuros: item.priceWeekdayEuros,
priceWeekendEuros: item.priceWeekendEuros,
contactName: "Sample Host",
contactEmail: SAMPLE_EMAIL,
contactPhone: owner.phone,
published: true,
status: ListingStatus.PUBLISHED,
approvedAt: new Date(),
},
});
await prisma.listingTranslation.upsert({
where: { slug_locale: { slug: item.slug, locale: "en" } },
create: {
listingId,
locale: "en",
slug: item.slug,
title: item.titleEn,
teaser: item.teaserEn,
description: item.descEn,
},
update: {
title: item.titleEn,
teaser: item.teaserEn,
description: item.descEn,
},
});
await prisma.listingTranslation.upsert({
where: { slug_locale: { slug: item.slug, locale: "fi" } },
create: {
listingId,
locale: "fi",
slug: item.slug,
title: item.titleFi,
teaser: item.teaserFi,
description: item.descFi,
},
update: {
title: item.titleFi,
teaser: item.teaserFi,
description: item.descFi,
},
});
await prisma.listingImage.deleteMany({ where: { listingId } });
if (imageCreates.length) {
await prisma.listingImage.createMany({
data: imageCreates.map((img) => ({
...img,
listingId,
})),
});
}
console.log("Updated listing:", item.slug);
}
console.log("Seed completed for sample listings.");
}
main()
.catch((e) => {
console.error(e);
process.exit(1);
})
.finally(async () => {
await prisma.$disconnect();
});