trips) adding package-tours option

This commit is contained in:
2026-02-19 13:08:25 -05:00
parent 50e216daec
commit dba9aa0416
51 changed files with 5581 additions and 57 deletions

View File

@@ -0,0 +1,313 @@
import { db } from '../db/index.js';
import type { Country } from '../plans.js';
import type { City } from '../plans.js';
import type { Airport, Airline } from '../flights.js';
// --- Countries ---
export function listCountries(query?: string): (Country & { id: number })[] {
if (!query?.trim()) {
return db.all<Country & { id: number }>(
'SELECT id, name, country_code FROM countries ORDER BY name'
);
}
const pattern = `%${query.trim()}%`;
return db.all<Country & { id: number }>(
`SELECT id, name, country_code FROM countries
WHERE name LIKE ? COLLATE NOCASE OR country_code LIKE ? COLLATE NOCASE
ORDER BY name LIMIT 200`,
[pattern, pattern]
);
}
export function createCountry(name: string, countryCode: string): Country & { id: number } {
db.run('INSERT INTO countries (name, country_code) VALUES (?, ?)', [
name.trim(),
countryCode.trim().toUpperCase()
]);
return db.get<Country & { id: number }>(
'SELECT id, name, country_code FROM countries WHERE country_code = ?',
[countryCode.trim().toUpperCase()]
)!;
}
export function updateCountry(id: number, name: string, countryCode: string): void {
db.run('UPDATE countries SET name = ?, country_code = ? WHERE id = ?', [
name.trim(),
countryCode.trim().toUpperCase(),
id
]);
}
export function deleteCountry(id: number): void {
db.run('DELETE FROM countries WHERE id = ?', [id]);
}
// --- Cities ---
export function listCities(query?: string, countryCode?: string): City[] {
if (!query?.trim()) {
if (countryCode?.trim()) {
return db.all<City>(
'SELECT id, name, country, country_code, population FROM cities WHERE country_code = ? ORDER BY name LIMIT 200',
[countryCode.trim().toUpperCase()]
);
}
return db.all<City>(
'SELECT id, name, country, country_code, population FROM cities ORDER BY name LIMIT 200'
);
}
const pattern = `%${query.trim()}%`;
if (countryCode?.trim()) {
return db.all<City>(
`SELECT id, name, country, country_code, population FROM cities
WHERE (name LIKE ? COLLATE NOCASE OR country LIKE ? COLLATE NOCASE) AND country_code = ?
ORDER BY name LIMIT 200`,
[pattern, pattern, countryCode.trim().toUpperCase()]
);
}
return db.all<City>(
`SELECT id, name, country, country_code, population FROM cities
WHERE name LIKE ? COLLATE NOCASE OR country LIKE ? COLLATE NOCASE
ORDER BY name LIMIT 200`,
[pattern, pattern]
);
}
export function createCity(
name: string,
country: string,
countryCode: string,
population?: number | null
): City {
const maxId = db.get<{ max: number }>('SELECT COALESCE(MAX(id), 0) + 1 as max FROM cities');
const id = maxId?.max ?? 1;
db.run(
'INSERT INTO cities (id, name, country, country_code, population) VALUES (?, ?, ?, ?, ?)',
[id, name.trim(), country.trim(), countryCode.trim().toUpperCase(), population ?? null]
);
return db.get<City>('SELECT * FROM cities WHERE id = ?', [id])!;
}
export function updateCity(
id: number,
name: string,
country: string,
countryCode: string,
population?: number | null
): void {
db.run('UPDATE cities SET name = ?, country = ?, country_code = ?, population = ? WHERE id = ?', [
name.trim(),
country.trim(),
countryCode.trim().toUpperCase(),
population ?? null,
id
]);
}
export function deleteCity(id: number): void {
db.run('DELETE FROM cities WHERE id = ?', [id]);
}
// --- Airports ---
export function listAirports(query?: string): Airport[] {
if (!query?.trim()) {
return db.all<Airport>('SELECT * FROM airports ORDER BY name LIMIT 200');
}
const pattern = `%${query.trim()}%`;
return db.all<Airport>(
`SELECT * FROM airports
WHERE name LIKE ? COLLATE NOCASE OR iata_code LIKE ? COLLATE NOCASE OR icao_code LIKE ? COLLATE NOCASE
OR city LIKE ? COLLATE NOCASE OR country LIKE ? COLLATE NOCASE
ORDER BY name LIMIT 200`,
[pattern, pattern, pattern, pattern, pattern]
);
}
export function createAirport(
name: string,
country: string,
countryCode: string,
iataCode?: string | null,
icaoCode?: string | null,
city?: string | null,
latitude?: number | null,
longitude?: number | null,
timezone?: string | null
): Airport {
db.run(
`INSERT INTO airports (name, city, country, country_code, iata_code, icao_code, latitude, longitude, timezone)
VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?)`,
[
name.trim(),
city?.trim() ?? null,
country.trim(),
countryCode.trim().toUpperCase(),
iataCode?.trim() ?? null,
icaoCode?.trim() ?? null,
latitude ?? null,
longitude ?? null,
timezone?.trim() ?? null
]
);
return db.get<Airport>('SELECT * FROM airports WHERE id = last_insert_rowid()')!;
}
export function updateAirport(
id: number,
name: string,
country: string,
countryCode: string,
iataCode?: string | null,
icaoCode?: string | null,
city?: string | null,
latitude?: number | null,
longitude?: number | null,
timezone?: string | null
): void {
db.run(
`UPDATE airports SET name = ?, city = ?, country = ?, country_code = ?,
iata_code = ?, icao_code = ?, latitude = ?, longitude = ?, timezone = ?
WHERE id = ?`,
[
name.trim(),
city?.trim() ?? null,
country.trim(),
countryCode.trim().toUpperCase(),
iataCode?.trim() ?? null,
icaoCode?.trim() ?? null,
latitude ?? null,
longitude ?? null,
timezone?.trim() ?? null,
id
]
);
}
export function deleteAirport(id: number): void {
db.run('DELETE FROM airports WHERE id = ?', [id]);
}
// --- Airlines ---
export function listAirlines(query?: string): Airline[] {
if (!query?.trim()) {
return db.all<Airline>('SELECT * FROM airlines ORDER BY name LIMIT 200');
}
const pattern = `%${query.trim()}%`;
return db.all<Airline>(
`SELECT * FROM airlines
WHERE name LIKE ? COLLATE NOCASE OR iata_code LIKE ? COLLATE NOCASE OR icao_code LIKE ? COLLATE NOCASE
OR country LIKE ? COLLATE NOCASE
ORDER BY name LIMIT 200`,
[pattern, pattern, pattern, pattern]
);
}
export function createAirline(
name: string,
country?: string | null,
countryCode?: string | null,
iataCode?: string | null,
icaoCode?: string | null
): Airline {
db.run(
'INSERT INTO airlines (name, country, country_code, iata_code, icao_code) VALUES (?, ?, ?, ?, ?)',
[
name.trim(),
country?.trim() ?? null,
countryCode?.trim()?.toUpperCase() ?? null,
iataCode?.trim() ?? null,
icaoCode?.trim() ?? null
]
);
return db.get<Airline>('SELECT * FROM airlines WHERE id = last_insert_rowid()')!;
}
export function updateAirline(
id: number,
name: string,
country?: string | null,
countryCode?: string | null,
iataCode?: string | null,
icaoCode?: string | null
): void {
db.run(
'UPDATE airlines SET name = ?, country = ?, country_code = ?, iata_code = ?, icao_code = ? WHERE id = ?',
[
name.trim(),
country?.trim() ?? null,
countryCode?.trim()?.toUpperCase() ?? null,
iataCode?.trim() ?? null,
icaoCode?.trim() ?? null,
id
]
);
}
export function deleteAirline(id: number): void {
db.run('DELETE FROM airlines WHERE id = ?', [id]);
}
// --- Tour Operators ---
export interface TourOperator {
id: number;
name: string;
website: string | null;
highlight_color: string | null;
created_at: string;
updated_at: string;
}
export function listTourOperators(query?: string): TourOperator[] {
if (!query?.trim()) {
return db.all<TourOperator>('SELECT * FROM tour_operators ORDER BY name');
}
const pattern = `%${query.trim()}%`;
return db.all<TourOperator>(
`SELECT * FROM tour_operators
WHERE name LIKE ? COLLATE NOCASE OR website LIKE ? COLLATE NOCASE
ORDER BY name LIMIT 200`,
[pattern, pattern]
);
}
export function createTourOperator(
name: string,
website?: string | null,
highlightColor?: string | null
): TourOperator {
db.run('INSERT INTO tour_operators (name, website, highlight_color) VALUES (?, ?, ?)', [
name.trim(),
website?.trim() ?? null,
highlightColor?.trim() ?? null
]);
return db.get<TourOperator>('SELECT * FROM tour_operators WHERE id = last_insert_rowid()')!;
}
export function updateTourOperator(
id: number,
name: string,
website?: string | null,
highlightColor?: string | null
): void {
db.run(
`UPDATE tour_operators SET name = ?, website = ?, highlight_color = ?,
updated_at = datetime('now') WHERE id = ?`,
[name.trim(), website?.trim() ?? null, highlightColor?.trim() ?? null, id]
);
}
export function deleteTourOperator(id: number): void {
db.run('DELETE FROM tour_operators WHERE id = ?', [id]);
}
export function getTourOperatorByName(name: string): TourOperator | null {
return (
db.get<TourOperator>('SELECT * FROM tour_operators WHERE name = ? COLLATE NOCASE', [
name.trim()
]) ?? null
);
}