/** * Seed industrial listings — 12 sample listings across 8 parks. * * Usage: npx tsx scripts/seed-industrial-listings.ts * Idempotent: uses upsert on id. */ import { PrismaPg } from '@prisma/adapter-pg'; import { PrismaClient, IndustrialPropertyType, IndustrialLeaseType, IndustrialListingStatus, } from '@prisma/client'; import pg from 'pg'; const pool = new pg.Pool({ connectionString: process.env['DATABASE_URL'] }); const adapter = new PrismaPg(pool); const prisma = new PrismaClient({ adapter }); interface IndustrialListingSeed { id: string; parkId: string; sellerId: string; agentId: string | null; propertyType: IndustrialPropertyType; leaseType: IndustrialLeaseType; status: IndustrialListingStatus; title: string; description: string; areaM2: number; ceilingHeightM: number | null; floorLoadTonM2: number | null; columnSpacingM: number | null; dockCount: number | null; craneCapacityTon: number | null; hasMezzanine: boolean; hasOfficeArea: boolean; officeAreaM2: number | null; priceUsdM2: number | null; pricingUnit: string | null; totalLeasePrice: number | null; managementFee: number | null; depositMonths: number | null; minLeaseYears: number | null; maxLeaseYears: number | null; availableFrom: Date | null; powerCapacityKva: number | null; waterSupplyM3Day: number | null; } const now = new Date(); const oneMonthLater = new Date(now.getTime() + 30 * 24 * 60 * 60 * 1000); const threeMonthsLater = new Date(now.getTime() + 90 * 24 * 60 * 60 * 1000); const LISTINGS: IndustrialListingSeed[] = [ // --- VSIP Bac Ninh (seed-kcn-001) — 2 listings --- { id: 'seed-ind-listing-001', parkId: 'seed-kcn-001', sellerId: 'seed-seller-001', agentId: 'seed-agentprofile-001', propertyType: IndustrialPropertyType.READY_BUILT_FACTORY, leaseType: IndustrialLeaseType.FACTORY_LEASE, status: IndustrialListingStatus.ACTIVE, title: 'Nhà xưởng xây sẵn 3.000m² KCN VSIP Bắc Ninh', description: 'Nhà xưởng xây sẵn tiêu chuẩn VSIP tại KCN VSIP Bắc Ninh. Kết cấu thép tiền chế, nền bê tông cốt thép chịu tải 3 tấn/m², hệ thống PCCC tự động, điện 3 pha 500kVA.', areaM2: 3000, ceilingHeightM: 10, floorLoadTonM2: 3, columnSpacingM: 12, dockCount: 4, craneCapacityTon: null, hasMezzanine: true, hasOfficeArea: true, officeAreaM2: 200, priceUsdM2: 5.5, pricingUnit: 'usd/m2/month', totalLeasePrice: 16500, managementFee: 0.7, depositMonths: 3, minLeaseYears: 3, maxLeaseYears: 10, availableFrom: oneMonthLater, powerCapacityKva: 500, waterSupplyM3Day: 50, }, { id: 'seed-ind-listing-002', parkId: 'seed-kcn-001', sellerId: 'seed-seller-002', agentId: null, propertyType: IndustrialPropertyType.INDUSTRIAL_LAND, leaseType: IndustrialLeaseType.LAND_LEASE, status: IndustrialListingStatus.ACTIVE, title: 'Đất công nghiệp 10.000m² VSIP Bắc Ninh — vị trí đắc địa', description: 'Lô đất công nghiệp mặt tiền đường chính 40m, gần cổng chính KCN. Phù hợp xây dựng nhà máy sản xuất điện tử, linh kiện.', areaM2: 10000, ceilingHeightM: null, floorLoadTonM2: null, columnSpacingM: null, dockCount: null, craneCapacityTon: null, hasMezzanine: false, hasOfficeArea: false, officeAreaM2: null, priceUsdM2: 90, pricingUnit: 'usd/m2/year', totalLeasePrice: 900000, managementFee: 0.7, depositMonths: 6, minLeaseYears: 20, maxLeaseYears: 50, availableFrom: now, powerCapacityKva: null, waterSupplyM3Day: null, }, // --- Amata Dong Nai (seed-kcn-003) — 2 listings --- { id: 'seed-ind-listing-003', parkId: 'seed-kcn-003', sellerId: 'seed-seller-001', agentId: 'seed-agentprofile-002', propertyType: IndustrialPropertyType.READY_BUILT_WAREHOUSE, leaseType: IndustrialLeaseType.WAREHOUSE_LEASE, status: IndustrialListingStatus.ACTIVE, title: 'Kho xưởng 5.000m² KCN Amata Đồng Nai — sẵn dock container', description: 'Kho xưởng xây sẵn với 6 dock container, hệ thống kệ pallet, nền chịu tải 5 tấn/m². Thích hợp logistics và phân phối.', areaM2: 5000, ceilingHeightM: 12, floorLoadTonM2: 5, columnSpacingM: 15, dockCount: 6, craneCapacityTon: 5, hasMezzanine: false, hasOfficeArea: true, officeAreaM2: 150, priceUsdM2: 5.0, pricingUnit: 'usd/m2/month', totalLeasePrice: 25000, managementFee: 0.65, depositMonths: 3, minLeaseYears: 2, maxLeaseYears: 10, availableFrom: oneMonthLater, powerCapacityKva: 300, waterSupplyM3Day: 30, }, { id: 'seed-ind-listing-004', parkId: 'seed-kcn-003', sellerId: 'seed-seller-002', agentId: 'seed-agentprofile-001', propertyType: IndustrialPropertyType.READY_BUILT_FACTORY, leaseType: IndustrialLeaseType.FACTORY_LEASE, status: IndustrialListingStatus.DRAFT, title: 'Nhà máy sản xuất 8.000m² Amata — cần bàn giao sớm', description: 'Nhà máy quy mô lớn với 2 bay sản xuất, cầu trục 10 tấn, hệ thống xử lý nước thải riêng. Đang hoàn thiện, dự kiến bàn giao Q3/2026.', areaM2: 8000, ceilingHeightM: 14, floorLoadTonM2: 5, columnSpacingM: 18, dockCount: 8, craneCapacityTon: 10, hasMezzanine: true, hasOfficeArea: true, officeAreaM2: 500, priceUsdM2: 4.8, pricingUnit: 'usd/m2/month', totalLeasePrice: 38400, managementFee: 0.65, depositMonths: 6, minLeaseYears: 5, maxLeaseYears: 20, availableFrom: threeMonthsLater, powerCapacityKva: 1500, waterSupplyM3Day: 100, }, // --- Nam Dinh Vu (seed-kcn-005) --- { id: 'seed-ind-listing-005', parkId: 'seed-kcn-005', sellerId: 'seed-seller-001', agentId: 'seed-agentprofile-003', propertyType: IndustrialPropertyType.LOGISTICS_CENTER, leaseType: IndustrialLeaseType.WAREHOUSE_LEASE, status: IndustrialListingStatus.ACTIVE, title: 'Trung tâm logistics 15.000m² KCN Nam Đình Vũ — sát cảng biển', description: 'Trung tâm logistics hiện đại ngay cảng Đình Vũ, phù hợp cho kho ngoại quan, trung chuyển hàng hóa quốc tế. Hệ thống bãi container 5.000m².', areaM2: 15000, ceilingHeightM: 12, floorLoadTonM2: 5, columnSpacingM: 20, dockCount: 12, craneCapacityTon: null, hasMezzanine: false, hasOfficeArea: true, officeAreaM2: 300, priceUsdM2: 4.8, pricingUnit: 'usd/m2/month', totalLeasePrice: 72000, managementFee: 0.6, depositMonths: 3, minLeaseYears: 3, maxLeaseYears: 15, availableFrom: now, powerCapacityKva: 800, waterSupplyM3Day: 60, }, // --- Long Hau (seed-kcn-006) --- { id: 'seed-ind-listing-006', parkId: 'seed-kcn-006', sellerId: 'seed-seller-002', agentId: 'seed-agentprofile-002', propertyType: IndustrialPropertyType.READY_BUILT_WAREHOUSE, leaseType: IndustrialLeaseType.SUBLEASE, status: IndustrialListingStatus.ACTIVE, title: 'Kho hàng 2.000m² Long Hậu — cho thuê lại giá tốt', description: 'Kho hàng cho thuê lại tại KCN Long Hậu, còn 4 năm hợp đồng gốc. Nền epoxy, PCCC đầy đủ, gần cảng Hiệp Phước.', areaM2: 2000, ceilingHeightM: 9, floorLoadTonM2: 3, columnSpacingM: 10, dockCount: 2, craneCapacityTon: null, hasMezzanine: false, hasOfficeArea: false, officeAreaM2: null, priceUsdM2: 4.0, pricingUnit: 'usd/m2/month', totalLeasePrice: 8000, managementFee: 0.5, depositMonths: 2, minLeaseYears: 1, maxLeaseYears: 4, availableFrom: now, powerCapacityKva: 200, waterSupplyM3Day: 15, }, // --- Thang Long II Hung Yen (seed-kcn-011) --- { id: 'seed-ind-listing-007', parkId: 'seed-kcn-011', sellerId: 'seed-seller-001', agentId: 'seed-agentprofile-001', propertyType: IndustrialPropertyType.READY_BUILT_FACTORY, leaseType: IndustrialLeaseType.FACTORY_LEASE, status: IndustrialListingStatus.ACTIVE, title: 'Xưởng sản xuất 4.500m² KCN Thăng Long II — tiêu chuẩn Nhật', description: 'Nhà xưởng tiêu chuẩn Nhật Bản tại KCN Thăng Long II Hưng Yên. Clean room sẵn, hệ thống AHU, phù hợp sản xuất linh kiện điện tử.', areaM2: 4500, ceilingHeightM: 10, floorLoadTonM2: 3, columnSpacingM: 12, dockCount: 4, craneCapacityTon: null, hasMezzanine: true, hasOfficeArea: true, officeAreaM2: 350, priceUsdM2: 4.5, pricingUnit: 'usd/m2/month', totalLeasePrice: 20250, managementFee: 0.6, depositMonths: 3, minLeaseYears: 3, maxLeaseYears: 15, availableFrom: oneMonthLater, powerCapacityKva: 600, waterSupplyM3Day: 40, }, // --- Yen Phong Bac Ninh (seed-kcn-012) --- { id: 'seed-ind-listing-008', parkId: 'seed-kcn-012', sellerId: 'seed-seller-002', agentId: null, propertyType: IndustrialPropertyType.INDUSTRIAL_LAND, leaseType: IndustrialLeaseType.LAND_LEASE, status: IndustrialListingStatus.ACTIVE, title: 'Đất công nghiệp 5.000m² Yên Phong — gần Samsung', description: 'Lô đất công nghiệp cuối cùng tại KCN Yên Phong, liền kề nhà máy Samsung Display. Hạ tầng hoàn chỉnh, phù hợp nhà cung cấp Samsung.', areaM2: 5000, ceilingHeightM: null, floorLoadTonM2: null, columnSpacingM: null, dockCount: null, craneCapacityTon: null, hasMezzanine: false, hasOfficeArea: false, officeAreaM2: null, priceUsdM2: 85, pricingUnit: 'usd/m2/year', totalLeasePrice: 425000, managementFee: 0.6, depositMonths: 6, minLeaseYears: 20, maxLeaseYears: 47, availableFrom: now, powerCapacityKva: null, waterSupplyM3Day: null, }, // --- DEEP C Hai Phong (seed-kcn-016) --- { id: 'seed-ind-listing-009', parkId: 'seed-kcn-016', sellerId: 'seed-seller-001', agentId: 'seed-agentprofile-003', propertyType: IndustrialPropertyType.READY_BUILT_FACTORY, leaseType: IndustrialLeaseType.FACTORY_LEASE, status: IndustrialListingStatus.ACTIVE, title: 'Nhà xưởng xanh 6.000m² DEEP C Hải Phòng — EDGE certified', description: 'Nhà xưởng đạt chứng chỉ EDGE Green Building, mái solar panels 200kWp, hệ thống thu gom nước mưa. Phù hợp doanh nghiệp ESG.', areaM2: 6000, ceilingHeightM: 11, floorLoadTonM2: 3, columnSpacingM: 15, dockCount: 6, craneCapacityTon: null, hasMezzanine: false, hasOfficeArea: true, officeAreaM2: 250, priceUsdM2: 4.5, pricingUnit: 'usd/m2/month', totalLeasePrice: 27000, managementFee: 0.6, depositMonths: 3, minLeaseYears: 3, maxLeaseYears: 15, availableFrom: threeMonthsLater, powerCapacityKva: 700, waterSupplyM3Day: 50, }, // --- My Phuoc 3 Binh Duong (seed-kcn-017) --- { id: 'seed-ind-listing-010', parkId: 'seed-kcn-017', sellerId: 'seed-seller-002', agentId: 'seed-agentprofile-002', propertyType: IndustrialPropertyType.READY_BUILT_WAREHOUSE, leaseType: IndustrialLeaseType.WAREHOUSE_LEASE, status: IndustrialListingStatus.ACTIVE, title: 'Kho xưởng 3.500m² Mỹ Phước 3 — gần đường Mỹ Phước Tân Vạn', description: 'Kho xưởng xây sẵn mặt đường nội khu, gần đường Mỹ Phước - Tân Vạn. Phù hợp kho hàng FMCG, logistics e-commerce.', areaM2: 3500, ceilingHeightM: 10, floorLoadTonM2: 3, columnSpacingM: 12, dockCount: 4, craneCapacityTon: null, hasMezzanine: false, hasOfficeArea: true, officeAreaM2: 100, priceUsdM2: 4.8, pricingUnit: 'usd/m2/month', totalLeasePrice: 16800, managementFee: 0.55, depositMonths: 3, minLeaseYears: 2, maxLeaseYears: 10, availableFrom: oneMonthLater, powerCapacityKva: 400, waterSupplyM3Day: 30, }, // --- KTG Nhon Trach (seed-kcn-009) --- { id: 'seed-ind-listing-011', parkId: 'seed-kcn-009', sellerId: 'seed-seller-001', agentId: 'seed-agentprofile-001', propertyType: IndustrialPropertyType.OFFICE_IN_PARK, leaseType: IndustrialLeaseType.FACTORY_LEASE, status: IndustrialListingStatus.DRAFT, title: 'Văn phòng trong KCN KTG Nhơn Trạch 500m²', description: 'Văn phòng mới xây trong KCN KTG Nhơn Trạch, 2 tầng, điều hòa trung tâm, bãi đỗ xe riêng. Phù hợp văn phòng vùng cho nhà máy lân cận.', areaM2: 500, ceilingHeightM: 3.5, floorLoadTonM2: null, columnSpacingM: null, dockCount: null, craneCapacityTon: null, hasMezzanine: false, hasOfficeArea: true, officeAreaM2: 500, priceUsdM2: 8.0, pricingUnit: 'usd/m2/month', totalLeasePrice: 4000, managementFee: 0.55, depositMonths: 2, minLeaseYears: 1, maxLeaseYears: 5, availableFrom: now, powerCapacityKva: 100, waterSupplyM3Day: 5, }, // --- Chu Lai Quang Nam (seed-kcn-020) --- { id: 'seed-ind-listing-012', parkId: 'seed-kcn-020', sellerId: 'seed-seller-002', agentId: 'seed-agentprofile-003', propertyType: IndustrialPropertyType.INDUSTRIAL_LAND, leaseType: IndustrialLeaseType.LAND_LEASE, status: IndustrialListingStatus.ACTIVE, title: 'Đất KCN Chu Lai 20.000m² — ưu đãi KKTM đặc biệt', description: 'Lô đất lớn tại KCN Chu Lai, thuộc Khu kinh tế mở Chu Lai với ưu đãi thuế đặc biệt: miễn tiền thuê đất 15 năm, miễn thuế NK toàn bộ. Phù hợp sản xuất ô tô, cơ khí.', areaM2: 20000, ceilingHeightM: null, floorLoadTonM2: null, columnSpacingM: null, dockCount: null, craneCapacityTon: null, hasMezzanine: false, hasOfficeArea: false, officeAreaM2: null, priceUsdM2: 40, pricingUnit: 'usd/m2/year', totalLeasePrice: 800000, managementFee: 0.35, depositMonths: 6, minLeaseYears: 20, maxLeaseYears: 50, availableFrom: now, powerCapacityKva: null, waterSupplyM3Day: null, }, ]; export async function seedIndustrialListings() { console.log('🏭 Seeding industrial listings...'); for (const l of LISTINGS) { const isPublished = l.status === IndustrialListingStatus.ACTIVE || l.status === IndustrialListingStatus.RESERVED; await prisma.industrialListing.upsert({ where: { id: l.id }, update: { title: l.title, status: l.status, priceUsdM2: l.priceUsdM2, totalLeasePrice: l.totalLeasePrice, }, create: { id: l.id, parkId: l.parkId, sellerId: l.sellerId, agentId: l.agentId, propertyType: l.propertyType, leaseType: l.leaseType, status: l.status, title: l.title, description: l.description, areaM2: l.areaM2, ceilingHeightM: l.ceilingHeightM, floorLoadTonM2: l.floorLoadTonM2, columnSpacingM: l.columnSpacingM, dockCount: l.dockCount, craneCapacityTon: l.craneCapacityTon, hasMezzanine: l.hasMezzanine, hasOfficeArea: l.hasOfficeArea, officeAreaM2: l.officeAreaM2, priceUsdM2: l.priceUsdM2, pricingUnit: l.pricingUnit, totalLeasePrice: l.totalLeasePrice, managementFee: l.managementFee, depositMonths: l.depositMonths, minLeaseYears: l.minLeaseYears, maxLeaseYears: l.maxLeaseYears, availableFrom: l.availableFrom, powerCapacityKva: l.powerCapacityKva, waterSupplyM3Day: l.waterSupplyM3Day, viewCount: Math.floor(Math.random() * 200) + 5, inquiryCount: Math.floor(Math.random() * 15), publishedAt: isPublished ? new Date() : null, }, }); console.log(` ✓ ${l.title.slice(0, 60)}...`); } console.log(`🏭 Seeded ${LISTINGS.length} industrial listings.`); } // Run standalone async function main() { try { await seedIndustrialListings(); } catch (err) { console.error('Seed error:', err); process.exit(1); } finally { await prisma.$disconnect(); await pool.end(); } } if (require.main === module) { void main(); }