trips) adding transportation, checklist, and experience planning
This commit is contained in:
@@ -211,6 +211,100 @@ export function runMigrations(db: Database): void {
|
||||
)
|
||||
`);
|
||||
|
||||
// Private vehicle transportation details - links to a transport plan
|
||||
db.run(`
|
||||
CREATE TABLE IF NOT EXISTS private_vehicles (
|
||||
id TEXT PRIMARY KEY,
|
||||
plan_id TEXT NOT NULL REFERENCES plans(id) ON DELETE CASCADE,
|
||||
start_address TEXT NOT NULL,
|
||||
end_address TEXT NOT NULL,
|
||||
departure_date TEXT,
|
||||
departure_time TEXT,
|
||||
departure_timezone TEXT,
|
||||
arrival_date TEXT,
|
||||
arrival_time TEXT,
|
||||
arrival_timezone TEXT,
|
||||
start_plan_id TEXT REFERENCES plans(id) ON DELETE SET NULL,
|
||||
end_plan_id TEXT REFERENCES plans(id) ON DELETE SET NULL,
|
||||
created_at TEXT NOT NULL DEFAULT (datetime('now')),
|
||||
updated_at TEXT NOT NULL DEFAULT (datetime('now'))
|
||||
)
|
||||
`);
|
||||
for (const col of [
|
||||
'departure_date TEXT',
|
||||
'departure_time TEXT',
|
||||
'departure_timezone TEXT',
|
||||
'arrival_date TEXT',
|
||||
'arrival_time TEXT',
|
||||
'arrival_timezone TEXT'
|
||||
]) {
|
||||
try {
|
||||
db.run(`ALTER TABLE private_vehicles ADD COLUMN ${col}`);
|
||||
} catch {
|
||||
/* already exists */
|
||||
}
|
||||
}
|
||||
|
||||
// Other transportation details - links to a transport plan
|
||||
db.run(`
|
||||
CREATE TABLE IF NOT EXISTS other_transports (
|
||||
id TEXT PRIMARY KEY,
|
||||
plan_id TEXT NOT NULL REFERENCES plans(id) ON DELETE CASCADE,
|
||||
start_date TEXT,
|
||||
start_time TEXT,
|
||||
start_timezone TEXT,
|
||||
end_date TEXT,
|
||||
end_time TEXT,
|
||||
end_timezone TEXT,
|
||||
created_at TEXT NOT NULL DEFAULT (datetime('now')),
|
||||
updated_at TEXT NOT NULL DEFAULT (datetime('now'))
|
||||
)
|
||||
`);
|
||||
|
||||
// Activity / restaurant details - links to a plan
|
||||
db.run(`
|
||||
CREATE TABLE IF NOT EXISTS experience_plans (
|
||||
id TEXT PRIMARY KEY,
|
||||
plan_id TEXT NOT NULL REFERENCES plans(id) ON DELETE CASCADE,
|
||||
booking_id TEXT,
|
||||
total_cost REAL,
|
||||
description TEXT,
|
||||
website TEXT,
|
||||
address TEXT,
|
||||
contact_number TEXT,
|
||||
start_date TEXT,
|
||||
start_time TEXT,
|
||||
start_timezone TEXT,
|
||||
end_date TEXT,
|
||||
end_time TEXT,
|
||||
end_timezone TEXT,
|
||||
created_at TEXT NOT NULL DEFAULT (datetime('now')),
|
||||
updated_at TEXT NOT NULL DEFAULT (datetime('now'))
|
||||
)
|
||||
`);
|
||||
|
||||
// Checklist master table (packing/todo details come from linked plan.type)
|
||||
db.run(`
|
||||
CREATE TABLE IF NOT EXISTS checklists (
|
||||
id TEXT PRIMARY KEY,
|
||||
plan_id TEXT NOT NULL REFERENCES plans(id) ON DELETE CASCADE,
|
||||
created_at TEXT NOT NULL DEFAULT (datetime('now')),
|
||||
updated_at TEXT NOT NULL DEFAULT (datetime('now'))
|
||||
)
|
||||
`);
|
||||
|
||||
db.run(`
|
||||
CREATE TABLE IF NOT EXISTS checklist_items (
|
||||
id TEXT PRIMARY KEY,
|
||||
checklist_id TEXT NOT NULL REFERENCES checklists(id) ON DELETE CASCADE,
|
||||
content TEXT NOT NULL,
|
||||
is_checked INTEGER NOT NULL DEFAULT 0,
|
||||
position INTEGER NOT NULL DEFAULT 0,
|
||||
created_at TEXT NOT NULL DEFAULT (datetime('now')),
|
||||
updated_at TEXT NOT NULL DEFAULT (datetime('now'))
|
||||
)
|
||||
`);
|
||||
|
||||
// Lodgings table - links to a plan
|
||||
db.run(`
|
||||
CREATE TABLE IF NOT EXISTS lodgings (
|
||||
@@ -330,12 +424,12 @@ export function runMigrations(db: Database): void {
|
||||
)
|
||||
`);
|
||||
|
||||
// Template plans (transport/lodging) attached to operator tour days
|
||||
// Template plans attached to operator tour days
|
||||
db.run(`
|
||||
CREATE TABLE IF NOT EXISTS operator_tour_day_plans (
|
||||
id INTEGER PRIMARY KEY AUTOINCREMENT,
|
||||
operator_tour_day_id INTEGER NOT NULL REFERENCES operator_tour_days(id) ON DELETE CASCADE,
|
||||
type TEXT NOT NULL CHECK (type IN ('transport', 'lodging')),
|
||||
type TEXT NOT NULL CHECK (type IN ('transport', 'lodging', 'activity', 'restaurant', 'packing', 'todo')),
|
||||
title TEXT NOT NULL,
|
||||
notes TEXT,
|
||||
position INTEGER NOT NULL DEFAULT 0,
|
||||
@@ -344,6 +438,65 @@ export function runMigrations(db: Database): void {
|
||||
)
|
||||
`);
|
||||
|
||||
// Migration: expand operator_tour_day_plans `type` CHECK constraint if it still only supports transport/lodging.
|
||||
try {
|
||||
const schema = db.get<{ sql: string }>(
|
||||
`SELECT sql FROM sqlite_master WHERE type = 'table' AND name = 'operator_tour_day_plans'`
|
||||
);
|
||||
const sql = schema?.sql?.toLowerCase() ?? '';
|
||||
if (sql && !sql.includes("'activity'")) {
|
||||
db.run(`
|
||||
CREATE TABLE operator_tour_day_plans__new (
|
||||
id INTEGER PRIMARY KEY AUTOINCREMENT,
|
||||
operator_tour_day_id INTEGER NOT NULL REFERENCES operator_tour_days(id) ON DELETE CASCADE,
|
||||
type TEXT NOT NULL CHECK (type IN ('transport', 'lodging', 'activity', 'restaurant', 'packing', 'todo')),
|
||||
title TEXT NOT NULL,
|
||||
notes TEXT,
|
||||
position INTEGER NOT NULL DEFAULT 0,
|
||||
created_at TEXT NOT NULL DEFAULT (datetime('now')),
|
||||
updated_at TEXT NOT NULL DEFAULT (datetime('now')),
|
||||
chain TEXT,
|
||||
address_line1 TEXT,
|
||||
address_line2 TEXT,
|
||||
city_name TEXT,
|
||||
country TEXT,
|
||||
country_code TEXT,
|
||||
postal_code TEXT,
|
||||
transport_kind TEXT,
|
||||
start_date TEXT,
|
||||
start_time TEXT,
|
||||
start_timezone TEXT,
|
||||
end_date TEXT,
|
||||
end_time TEXT,
|
||||
end_timezone TEXT,
|
||||
booking_id TEXT,
|
||||
total_cost REAL,
|
||||
description TEXT,
|
||||
website TEXT,
|
||||
address TEXT,
|
||||
contact_number TEXT,
|
||||
items_json TEXT
|
||||
)
|
||||
`);
|
||||
db.run(`
|
||||
INSERT INTO operator_tour_day_plans__new (
|
||||
id, operator_tour_day_id, type, title, notes, position, created_at, updated_at,
|
||||
chain, address_line1, address_line2, city_name, country, country_code, postal_code,
|
||||
transport_kind, start_date, start_time, start_timezone, end_date, end_time, end_timezone
|
||||
)
|
||||
SELECT
|
||||
id, operator_tour_day_id, type, title, notes, position, created_at, updated_at,
|
||||
chain, address_line1, address_line2, city_name, country, country_code, postal_code,
|
||||
transport_kind, start_date, start_time, start_timezone, end_date, end_time, end_timezone
|
||||
FROM operator_tour_day_plans
|
||||
`);
|
||||
db.run('DROP TABLE operator_tour_day_plans');
|
||||
db.run('ALTER TABLE operator_tour_day_plans__new RENAME TO operator_tour_day_plans');
|
||||
}
|
||||
} catch {
|
||||
/* best-effort migration */
|
||||
}
|
||||
|
||||
// Lodging-specific fields for operator_tour_day_plans (type=lodging) — same shape as trip lodgings
|
||||
for (const col of [
|
||||
'chain TEXT',
|
||||
@@ -352,7 +505,21 @@ export function runMigrations(db: Database): void {
|
||||
'city_name TEXT',
|
||||
'country TEXT',
|
||||
'country_code TEXT',
|
||||
'postal_code TEXT'
|
||||
'postal_code TEXT',
|
||||
'transport_kind TEXT',
|
||||
'start_date TEXT',
|
||||
'start_time TEXT',
|
||||
'start_timezone TEXT',
|
||||
'end_date TEXT',
|
||||
'end_time TEXT',
|
||||
'end_timezone TEXT',
|
||||
'booking_id TEXT',
|
||||
'total_cost REAL',
|
||||
'description TEXT',
|
||||
'website TEXT',
|
||||
'address TEXT',
|
||||
'contact_number TEXT',
|
||||
'items_json TEXT'
|
||||
]) {
|
||||
try {
|
||||
db.run(`ALTER TABLE operator_tour_day_plans ADD COLUMN ${col}`);
|
||||
@@ -360,6 +527,15 @@ export function runMigrations(db: Database): void {
|
||||
/* already exists */
|
||||
}
|
||||
}
|
||||
try {
|
||||
db.run(
|
||||
`UPDATE operator_tour_day_plans
|
||||
SET transport_kind = 'other'
|
||||
WHERE type = 'transport' AND (transport_kind IS NULL OR TRIM(transport_kind) = '')`
|
||||
);
|
||||
} catch {
|
||||
/* best-effort migration */
|
||||
}
|
||||
|
||||
// Countries table — editable list for admin (used by country selector)
|
||||
db.run(`
|
||||
|
||||
Reference in New Issue
Block a user