From b22543d59e86da8ba2a4284b72fc52d0f22301c2 Mon Sep 17 00:00:00 2001 From: Ho Ngoc Hai Date: Thu, 16 Apr 2026 14:18:41 +0700 Subject: [PATCH] feat(seed): add MacroeconomicData and InfrastructureProject seed data Add seed-macro-infra.ts with 144 macroeconomic data points (HCMC + Hanoi, 6 indicators, quarterly 2023-2025) and 15 infrastructure projects with PostGIS coordinates (Metro Line 1, Thu Duc Innovation District, Ring Road 3, Long Thanh Airport, Can Gio Bridge, etc.). Integrated into main seed pipeline. Co-Authored-By: Paperclip --- prisma/seed.ts | 16 +- scripts/seed-macro-infra.ts | 401 ++++++++++++++++++++++++++++++++++++ 2 files changed, 415 insertions(+), 2 deletions(-) create mode 100644 scripts/seed-macro-infra.ts diff --git a/prisma/seed.ts b/prisma/seed.ts index c218fae..f06a6b0 100644 --- a/prisma/seed.ts +++ b/prisma/seed.ts @@ -36,7 +36,9 @@ import { import bcrypt from 'bcrypt'; import pg from 'pg'; import { importMarketData } from '../scripts/import-market-data'; +import { seedIndustrialListings } from '../scripts/seed-industrial-listings'; import { seedIndustrialParks } from '../scripts/seed-industrial-parks'; +import { seedMacroAndInfra } from '../scripts/seed-macro-infra'; import { seedPlans } from '../scripts/seed-plans'; import { seedPOIs } from '../scripts/seed-pois'; @@ -753,7 +755,15 @@ async function main() { await seedIndustrialParks(); console.log(''); - // Phase 12 — Market Data + // Phase 11b — Industrial Listings + await seedIndustrialListings(); + console.log(''); + + // Phase 12 — Macroeconomic Data & Infrastructure Projects + await seedMacroAndInfra(prisma); + console.log(''); + + // Phase 13 — Market Data await importMarketData(); console.log('\n' + '━'.repeat(60)); @@ -780,7 +790,9 @@ async function main() { console.log(' Saved Searches: 4'); console.log(' Notifications: 10 + 6 prefs'); console.log(' Audit Logs: 5'); - console.log(' Industrial: 20 parks'); + console.log(' Industrial: 20 parks + 12 listings'); + console.log(' Macro Data: 144 data points (HCMC + Hanoi, quarterly)'); + console.log(' Infra Projects: 15 (metro, highway, airport, bridge, port)'); console.log(' Market Index: ~240 records'); console.log('\n🔐 Admin Login:'); console.log(' Phone: 0876677771'); diff --git a/scripts/seed-macro-infra.ts b/scripts/seed-macro-infra.ts new file mode 100644 index 0000000..6ea8403 --- /dev/null +++ b/scripts/seed-macro-infra.ts @@ -0,0 +1,401 @@ +/** + * Seed MacroeconomicData and InfrastructureProject tables. + * + * MacroeconomicData: 50+ rows — HCMC & Hanoi, quarterly 2023-Q1 → 2025-Q4. + * InfrastructureProject: 15 real projects with coordinates, status, dates, investment. + */ + +import { type PrismaClient } from '@prisma/client'; + +// ============================================================================= +// MacroeconomicData — HCMC & Hanoi, quarterly 2023–2025 +// ============================================================================= + +interface MacroRow { + province: string; + indicator: string; + value: number; + unit: string; + period: string; + source: string; +} + +const QUARTERS = [ + '2023-Q1', '2023-Q2', '2023-Q3', '2023-Q4', + '2024-Q1', '2024-Q2', '2024-Q3', '2024-Q4', + '2025-Q1', '2025-Q2', '2025-Q3', '2025-Q4', +]; + +/** + * Helper: generate quarterly series with a base value and per-quarter growth. + */ +function quarterlySeries( + province: string, + indicator: string, + unit: string, + source: string, + baseValue: number, + quarterlyGrowth: number, +): MacroRow[] { + return QUARTERS.map((period, i) => ({ + province, + indicator, + value: Math.round((baseValue + baseValue * quarterlyGrowth * i) * 100) / 100, + unit, + period, + source, + })); +} + +function buildMacroData(): MacroRow[] { + const rows: MacroRow[] = []; + + // ── Hồ Chí Minh ────────────────────────────────────────── + + // GDP growth (% YoY per quarter) + const hcmcGdpGrowth = [5.8, 6.1, 6.4, 6.7, 6.2, 6.5, 6.8, 7.1, 6.9, 7.2, 7.0, 7.3]; + QUARTERS.forEach((q, i) => rows.push({ province: 'Hồ Chí Minh', indicator: 'gdp_growth', value: hcmcGdpGrowth[i]!, unit: '%', period: q, source: 'GSO' })); + + // CPI (% YoY) + const hcmcCpi = [3.1, 3.3, 3.5, 3.8, 4.0, 3.9, 4.1, 4.2, 3.8, 3.6, 3.5, 3.4]; + QUARTERS.forEach((q, i) => rows.push({ province: 'Hồ Chí Minh', indicator: 'cpi', value: hcmcCpi[i]!, unit: '%', period: q, source: 'GSO' })); + + // Population (persons, grows slowly) + rows.push(...quarterlySeries('Hồ Chí Minh', 'population', 'người', 'GSO', 9_800_000, 0.003)); + + // Construction permits (number per quarter) + const hcmcPermits = [1250, 1380, 1420, 1510, 1320, 1460, 1550, 1620, 1480, 1590, 1650, 1720]; + QUARTERS.forEach((q, i) => rows.push({ province: 'Hồ Chí Minh', indicator: 'construction_permits', value: hcmcPermits[i]!, unit: 'giấy phép', period: q, source: 'Sở Xây dựng TP.HCM' })); + + // FDI (million USD per quarter) + const hcmcFdi = [1650, 1800, 1920, 2050, 1780, 1950, 2100, 2200, 1900, 2080, 2150, 2300]; + QUARTERS.forEach((q, i) => rows.push({ province: 'Hồ Chí Minh', indicator: 'fdi', value: hcmcFdi[i]!, unit: 'triệu USD', period: q, source: 'GSO' })); + + // RE transaction volume (number of transactions per quarter) + const hcmcTxVol = [8500, 9200, 10100, 11500, 9800, 10500, 11200, 12800, 10200, 11000, 11800, 13500]; + QUARTERS.forEach((q, i) => rows.push({ province: 'Hồ Chí Minh', indicator: 're_transaction_volume', value: hcmcTxVol[i]!, unit: 'giao dịch', period: q, source: 'Sở Xây dựng TP.HCM' })); + + // ── Hà Nội ──────────────────────────────────────────────── + + // GDP growth + const hanoiGdpGrowth = [5.2, 5.5, 5.8, 6.0, 5.9, 6.2, 6.5, 6.8, 6.4, 6.7, 6.9, 7.1]; + QUARTERS.forEach((q, i) => rows.push({ province: 'Hà Nội', indicator: 'gdp_growth', value: hanoiGdpGrowth[i]!, unit: '%', period: q, source: 'GSO' })); + + // CPI + const hanoiCpi = [2.8, 3.0, 3.2, 3.5, 3.7, 3.6, 3.8, 3.9, 3.5, 3.3, 3.2, 3.1]; + QUARTERS.forEach((q, i) => rows.push({ province: 'Hà Nội', indicator: 'cpi', value: hanoiCpi[i]!, unit: '%', period: q, source: 'GSO' })); + + // Population + rows.push(...quarterlySeries('Hà Nội', 'population', 'người', 'GSO', 8_400_000, 0.0025)); + + // Construction permits + const hanoiPermits = [980, 1050, 1120, 1200, 1060, 1150, 1230, 1310, 1180, 1260, 1340, 1420]; + QUARTERS.forEach((q, i) => rows.push({ province: 'Hà Nội', indicator: 'construction_permits', value: hanoiPermits[i]!, unit: 'giấy phép', period: q, source: 'Sở Xây dựng Hà Nội' })); + + // FDI + const hanoiFdi = [1400, 1520, 1650, 1750, 1500, 1620, 1780, 1850, 1600, 1730, 1820, 1950]; + QUARTERS.forEach((q, i) => rows.push({ province: 'Hà Nội', indicator: 'fdi', value: hanoiFdi[i]!, unit: 'triệu USD', period: q, source: 'GSO' })); + + // RE transaction volume + const hanoiTxVol = [7200, 7800, 8500, 9600, 8100, 8800, 9500, 10800, 8600, 9300, 10000, 11200]; + QUARTERS.forEach((q, i) => rows.push({ province: 'Hà Nội', indicator: 're_transaction_volume', value: hanoiTxVol[i]!, unit: 'giao dịch', period: q, source: 'Sở Xây dựng Hà Nội' })); + + return rows; +} + +// ============================================================================= +// InfrastructureProject — 15 real projects with coordinates +// ============================================================================= + +interface InfraRow { + name: string; + province: string; + category: string; + status: string; + investmentVND: bigint; + startDate: Date | null; + completionDate: Date | null; + description: string; + impactRadius: number; + lat: number; + lng: number; +} + +function buildInfraProjects(): InfraRow[] { + return [ + // 1. Metro Line 1 (Bến Thành – Suối Tiên) + { + name: 'Metro Bến Thành – Suối Tiên (Tuyến 1)', + province: 'Hồ Chí Minh', + category: 'metro', + status: 'completed', + investmentVND: BigInt(43_700_000_000_000), + startDate: new Date('2012-08-28'), + completionDate: new Date('2024-12-22'), + description: 'Tuyến metro đầu tiên TP.HCM, 19.7km, 14 ga. Kết nối Quận 1 – Thủ Đức – Bình Dương.', + impactRadius: 3.0, + lat: 10.7721, + lng: 106.6980, + }, + // 2. Metro Line 2 (Bến Thành – Tham Lương) + { + name: 'Metro Bến Thành – Tham Lương (Tuyến 2)', + province: 'Hồ Chí Minh', + category: 'metro', + status: 'planning', + investmentVND: BigInt(47_800_000_000_000), + startDate: new Date('2026-06-01'), + completionDate: new Date('2032-12-01'), + description: 'Tuyến metro số 2, 11.3km, 10 ga. Kết nối trung tâm đến Tân Bình, Q12.', + impactRadius: 2.5, + lat: 10.7731, + lng: 106.6930, + }, + // 3. Thu Duc Innovation District (Khu đô thị sáng tạo Thủ Đức) + { + name: 'Khu Đô thị Sáng tạo Tương tác cao phía Đông (Thủ Đức)', + province: 'Hồ Chí Minh', + category: 'urban_development', + status: 'under_construction', + investmentVND: BigInt(300_000_000_000_000), + startDate: new Date('2020-01-01'), + completionDate: new Date('2040-12-01'), + description: 'Siêu dự án đô thị sáng tạo 21,172ha tại TP. Thủ Đức, gồm khu công nghệ cao, tài chính, giáo dục.', + impactRadius: 10.0, + lat: 10.8231, + lng: 106.7620, + }, + // 4. Ring Road 3 (Vành đai 3 TP.HCM) + { + name: 'Đường Vành đai 3 TP.HCM', + province: 'Hồ Chí Minh', + category: 'highway', + status: 'under_construction', + investmentVND: BigInt(75_400_000_000_000), + startDate: new Date('2023-06-18'), + completionDate: new Date('2026-12-01'), + description: 'Tuyến vành đai 76km qua TP.HCM, Bình Dương, Đồng Nai, Long An. 4-8 làn xe.', + impactRadius: 5.0, + lat: 10.8500, + lng: 106.7800, + }, + // 5. Long Thanh International Airport — Phase 1 + { + name: 'Cảng Hàng không Quốc tế Long Thành – Giai đoạn 1', + province: 'Đồng Nai', + category: 'airport', + status: 'under_construction', + investmentVND: BigInt(109_000_000_000_000), + startDate: new Date('2021-01-05'), + completionDate: new Date('2026-12-01'), + description: 'Sân bay quốc tế mới, công suất 25 triệu HK/năm (GĐ1), 100 triệu HK/năm (hoàn thành).', + impactRadius: 15.0, + lat: 10.9730, + lng: 107.0070, + }, + // 6. Can Gio Bridge (Cầu Cần Giờ) + { + name: 'Cầu Cần Giờ', + province: 'Hồ Chí Minh', + category: 'bridge', + status: 'planning', + investmentVND: BigInt(10_000_000_000_000), + startDate: new Date('2025-12-01'), + completionDate: new Date('2028-12-01'), + description: 'Cầu dây văng nối Nhà Bè – Cần Giờ, dài ~3.4km, rộng 6 làn xe. Mở khóa tiềm năng du lịch & BĐS Cần Giờ.', + impactRadius: 8.0, + lat: 10.6190, + lng: 106.7530, + }, + // 7. Cao tốc TP.HCM – Long Thành – Dầu Giây (mở rộng) + { + name: 'Cao tốc TP.HCM – Long Thành – Dầu Giây (mở rộng)', + province: 'Hồ Chí Minh', + category: 'highway', + status: 'under_construction', + investmentVND: BigInt(9_000_000_000_000), + startDate: new Date('2024-03-01'), + completionDate: new Date('2027-06-01'), + description: 'Mở rộng từ 4 lên 8-10 làn xe, 55km. Giảm ùn tắc kết nối sân bay Long Thành.', + impactRadius: 4.0, + lat: 10.8350, + lng: 106.8600, + }, + // 8. Cao tốc Bến Lức – Long Thành + { + name: 'Cao tốc Bến Lức – Long Thành', + province: 'Đồng Nai', + category: 'highway', + status: 'under_construction', + investmentVND: BigInt(31_300_000_000_000), + startDate: new Date('2014-07-01'), + completionDate: new Date('2026-09-01'), + description: 'Tuyến cao tốc 57.8km kết nối Long An – TP.HCM – Đồng Nai, vượt sông Sài Gòn.', + impactRadius: 5.0, + lat: 10.7200, + lng: 106.8500, + }, + // 9. Metro Line 3 Hà Nội (Nhổn – Ga Hà Nội) + { + name: 'Metro Nhổn – Ga Hà Nội (Tuyến 3)', + province: 'Hà Nội', + category: 'metro', + status: 'under_construction', + investmentVND: BigInt(34_800_000_000_000), + startDate: new Date('2010-09-01'), + completionDate: new Date('2027-12-01'), + description: 'Tuyến metro 12.5km, 12 ga, kết nối Nhổn – Cầu Giấy – ga Hà Nội.', + impactRadius: 2.5, + lat: 21.0285, + lng: 105.8542, + }, + // 10. Metro Line 2A Hà Nội (Cát Linh – Hà Đông) + { + name: 'Metro Cát Linh – Hà Đông (Tuyến 2A)', + province: 'Hà Nội', + category: 'metro', + status: 'completed', + investmentVND: BigInt(18_000_000_000_000), + startDate: new Date('2011-10-10'), + completionDate: new Date('2021-11-06'), + description: 'Tuyến đường sắt trên cao đầu tiên Hà Nội, 13.1km, 12 ga.', + impactRadius: 2.0, + lat: 21.0033, + lng: 105.8245, + }, + // 11. Vành đai 4 Hà Nội + { + name: 'Đường Vành đai 4 – Vùng Thủ đô Hà Nội', + province: 'Hà Nội', + category: 'highway', + status: 'under_construction', + investmentVND: BigInt(85_800_000_000_000), + startDate: new Date('2023-06-25'), + completionDate: new Date('2027-12-01'), + description: 'Tuyến vành đai 112km qua Hà Nội, Hưng Yên, Bắc Ninh. 6 làn cao tốc.', + impactRadius: 6.0, + lat: 21.0500, + lng: 105.9000, + }, + // 12. Sân bay Tân Sơn Nhất – Nhà ga T3 + { + name: 'Nhà ga T3 Sân bay Tân Sơn Nhất', + province: 'Hồ Chí Minh', + category: 'airport', + status: 'under_construction', + investmentVND: BigInt(10_990_000_000_000), + startDate: new Date('2022-12-01'), + completionDate: new Date('2025-04-30'), + description: 'Nhà ga hành khách T3, công suất 20 triệu HK/năm, nâng tổng công suất TSN lên 50 triệu.', + impactRadius: 5.0, + lat: 10.8188, + lng: 106.6590, + }, + // 13. Cảng trung chuyển quốc tế Cần Giờ + { + name: 'Cảng Trung chuyển Quốc tế Cần Giờ', + province: 'Hồ Chí Minh', + category: 'port', + status: 'planning', + investmentVND: BigInt(113_000_000_000_000), + startDate: new Date('2025-06-01'), + completionDate: new Date('2035-12-01'), + description: 'Siêu cảng trung chuyển container quốc tế tại Cần Giờ, công suất 10-15 triệu TEU/năm.', + impactRadius: 12.0, + lat: 10.4110, + lng: 106.9480, + }, + // 14. Đường sắt tốc độ cao Bắc – Nam (GĐ1) + { + name: 'Đường sắt Tốc độ cao Bắc – Nam (Giai đoạn 1)', + province: 'Hà Nội', + category: 'railway', + status: 'planning', + investmentVND: BigInt(670_000_000_000_000), + startDate: new Date('2027-01-01'), + completionDate: new Date('2035-12-01'), + description: 'Đoạn Hà Nội – Vinh & Nha Trang – TP.HCM, tốc độ thiết kế 350km/h.', + impactRadius: 10.0, + lat: 21.0028, + lng: 105.8440, + }, + // 15. Cao tốc Mỹ Phước – Tân Vạn (mở rộng) + { + name: 'Cao tốc Mỹ Phước – Tân Vạn (mở rộng)', + province: 'Bình Dương', + category: 'highway', + status: 'under_construction', + investmentVND: BigInt(4_500_000_000_000), + startDate: new Date('2023-09-01'), + completionDate: new Date('2026-06-01'), + description: 'Mở rộng kết nối các KCN Bình Dương với TP.HCM, từ 4 lên 8 làn xe.', + impactRadius: 3.0, + lat: 10.9800, + lng: 106.6530, + }, + ]; +} + +// ============================================================================= +// Public seed function +// ============================================================================= + +export async function seedMacroAndInfra(prisma: PrismaClient) { + console.log('📈 Seeding macroeconomic data...'); + + const macroData = buildMacroData(); + for (const d of macroData) { + await prisma.macroeconomicData.upsert({ + where: { + province_indicator_period: { + province: d.province, + indicator: d.indicator, + period: d.period, + }, + }, + create: d, + update: { value: d.value, unit: d.unit, source: d.source }, + }); + } + console.log(` ✓ ${macroData.length} macroeconomic data points seeded (HCMC + Hanoi, quarterly 2023–2025)`); + + console.log('🏗️ Seeding infrastructure projects...'); + + const infraProjects = buildInfraProjects(); + for (const p of infraProjects) { + const existing = await prisma.infrastructureProject.findFirst({ + where: { name: p.name, province: p.province }, + }); + if (existing) { + // Update existing record with coordinates and dates if missing + await prisma.$executeRaw` + UPDATE "InfrastructureProject" + SET "status" = ${p.status}, + "investmentVND" = ${p.investmentVND}, + "startDate" = ${p.startDate}, + "completionDate" = ${p.completionDate}, + "description" = ${p.description}, + "impactRadius" = ${p.impactRadius}, + "location" = ST_SetSRID(ST_MakePoint(${p.lng}, ${p.lat}), 4326), + "updatedAt" = NOW() + WHERE "id" = ${existing.id} + `; + } else { + await prisma.$executeRaw` + INSERT INTO "InfrastructureProject" ( + "id", "name", "province", "category", "status", + "investmentVND", "startDate", "completionDate", + "description", "impactRadius", "location", + "createdAt", "updatedAt" + ) VALUES ( + gen_random_uuid(), ${p.name}, ${p.province}, ${p.category}, ${p.status}, + ${p.investmentVND}, ${p.startDate}, ${p.completionDate}, + ${p.description}, ${p.impactRadius}, + ST_SetSRID(ST_MakePoint(${p.lng}, ${p.lat}), 4326), + NOW(), NOW() + ) + `; + } + } + console.log(` ✓ ${infraProjects.length} infrastructure projects seeded (with coordinates)`); +}