trips) adding package-tours option
This commit is contained in:
@@ -249,12 +249,71 @@ export function runMigrations(db: Database): void {
|
||||
)
|
||||
`);
|
||||
|
||||
// Package tours table - links to a plan
|
||||
db.run(`
|
||||
CREATE TABLE IF NOT EXISTS package_tours (
|
||||
id TEXT PRIMARY KEY,
|
||||
plan_id TEXT NOT NULL REFERENCES plans(id) ON DELETE CASCADE,
|
||||
operator_name TEXT NOT NULL,
|
||||
confirmation_number TEXT,
|
||||
start_date TEXT,
|
||||
start_time TEXT,
|
||||
start_timezone TEXT,
|
||||
end_date TEXT,
|
||||
end_time TEXT,
|
||||
end_timezone TEXT,
|
||||
price REAL,
|
||||
currency TEXT NOT NULL DEFAULT 'USD',
|
||||
created_at TEXT NOT NULL DEFAULT (datetime('now')),
|
||||
updated_at TEXT NOT NULL DEFAULT (datetime('now'))
|
||||
)
|
||||
`);
|
||||
|
||||
// Package tour travellers - links people to package tours
|
||||
db.run(`
|
||||
CREATE TABLE IF NOT EXISTS package_tour_travellers (
|
||||
package_tour_id TEXT NOT NULL REFERENCES package_tours(id) ON DELETE CASCADE,
|
||||
person_id TEXT NOT NULL REFERENCES people(id) ON DELETE CASCADE,
|
||||
PRIMARY KEY (package_tour_id, person_id)
|
||||
)
|
||||
`);
|
||||
|
||||
// Tour operators reference table
|
||||
db.run(`
|
||||
CREATE TABLE IF NOT EXISTS tour_operators (
|
||||
id INTEGER PRIMARY KEY AUTOINCREMENT,
|
||||
name TEXT NOT NULL UNIQUE,
|
||||
website TEXT,
|
||||
highlight_color TEXT,
|
||||
created_at TEXT NOT NULL DEFAULT (datetime('now')),
|
||||
updated_at TEXT NOT NULL DEFAULT (datetime('now'))
|
||||
)
|
||||
`);
|
||||
|
||||
// Countries table — editable list for admin (used by country selector)
|
||||
db.run(`
|
||||
CREATE TABLE IF NOT EXISTS countries (
|
||||
id INTEGER PRIMARY KEY,
|
||||
name TEXT NOT NULL,
|
||||
country_code TEXT NOT NULL UNIQUE
|
||||
)
|
||||
`);
|
||||
|
||||
// Seed cities table on first run
|
||||
const row = db.get<{ count: number }>('SELECT COUNT(*) as count FROM cities');
|
||||
if ((row?.count ?? 0) === 0) {
|
||||
seedCities(db);
|
||||
}
|
||||
|
||||
// Seed countries from cities if empty
|
||||
const countriesRow = db.get<{ count: number }>('SELECT COUNT(*) as count FROM countries');
|
||||
if ((countriesRow?.count ?? 0) === 0) {
|
||||
db.run(`
|
||||
INSERT OR IGNORE INTO countries (name, country_code)
|
||||
SELECT DISTINCT country, country_code FROM cities ORDER BY country
|
||||
`);
|
||||
}
|
||||
|
||||
// Seed airports and airlines on first run only
|
||||
const airportsRow = db.get<{ count: number }>('SELECT COUNT(*) as count FROM airports');
|
||||
if ((airportsRow?.count ?? 0) === 0) {
|
||||
@@ -306,7 +365,7 @@ function seedAirports(db: Database): void {
|
||||
// OpenFlights format: ID, Name, City, Country, IATA, ICAO, Lat, Lon, Alt, TZ, DST, TZ_DB, Type, Source
|
||||
if (fields.length < 8) continue;
|
||||
|
||||
const [idStr, name, city, country, iata, icao, latStr, lonStr, , , , tzDb] = fields;
|
||||
const [_idStr, name, city, country, iata, icao, latStr, lonStr, , , , tzDb] = fields;
|
||||
|
||||
// Skip if missing essential data
|
||||
if (!name || !country) {
|
||||
@@ -344,14 +403,14 @@ function seedAirports(db: Database): void {
|
||||
]
|
||||
);
|
||||
imported++;
|
||||
} catch (err) {
|
||||
} catch (_err) {
|
||||
// Skip duplicates or invalid data
|
||||
skipped++;
|
||||
}
|
||||
}
|
||||
console.log(`[db] Seeded ${imported} airports from airports.dat (${skipped} skipped)`);
|
||||
return;
|
||||
} catch (fileError) {
|
||||
} catch (_fileError) {
|
||||
// File doesn't exist, fall back to minimal seed only if table is empty
|
||||
const airportsRow = db.get<{ count: number }>('SELECT COUNT(*) as count FROM airports');
|
||||
if ((airportsRow?.count ?? 0) === 0) {
|
||||
@@ -500,7 +559,7 @@ function seedAirlines(db: Database): void {
|
||||
// OpenFlights format: ID, Name, Alias, IATA, ICAO, Callsign, Country, Active
|
||||
if (fields.length < 7) continue;
|
||||
|
||||
const [idStr, name, , iata, icao, , country, active] = fields;
|
||||
const [_idStr, name, , iata, icao, , country, active] = fields;
|
||||
|
||||
// Skip if missing essential data or inactive
|
||||
if (!name || !country || active !== 'Y') {
|
||||
@@ -525,14 +584,14 @@ function seedAirlines(db: Database): void {
|
||||
[iata || null, icao || null, name, country, countryCode]
|
||||
);
|
||||
imported++;
|
||||
} catch (err) {
|
||||
} catch (_err) {
|
||||
// Skip duplicates or invalid data
|
||||
skipped++;
|
||||
}
|
||||
}
|
||||
console.log(`[db] Seeded ${imported} airlines from airlines.dat (${skipped} skipped)`);
|
||||
return;
|
||||
} catch (fileError) {
|
||||
} catch (_fileError) {
|
||||
// File doesn't exist, fall back to minimal seed only if table is empty
|
||||
const airlinesRow = db.get<{ count: number }>('SELECT COUNT(*) as count FROM airlines');
|
||||
if ((airlinesRow?.count ?? 0) === 0) {
|
||||
|
||||
Reference in New Issue
Block a user