diff --git a/requests.http b/requests.http index 3bea1c1..8ba616c 100644 --- a/requests.http +++ b/requests.http @@ -18,4 +18,16 @@ GET http://localhost:3000/api/passengers/123456789 GET http://localhost:3000/api/airports/?icaoCodes=true ### get one airports -GET http://localhost:3000/api/airports/EDDF \ No newline at end of file +GET http://localhost:3000/api/airports/EDDF + +### +PUT http://localhost:3000/api/flights/AB123 +Content-Type: application/json + +{ + "departure": "2023-12-01T10:00:00.000Z", + "arrival": "2023-12-01T14:00:00.000Z", + "operates": "OE-LAB", + "departs": "LOWW", + "arrives": "EDDF" +} \ No newline at end of file diff --git a/src/database/data.ts b/src/database/data.ts index 8044f7d..3fb2c6d 100644 --- a/src/database/data.ts +++ b/src/database/data.ts @@ -6,7 +6,7 @@ import {PlaneModel} from "../models/plane.model"; export class DB { - static async createDBConnection() : Promise { + static async createDBConnection(): Promise { const connection = await open({ filename: `./flights.db`, driver: sqlite3.Database @@ -29,79 +29,75 @@ export class DB { await db.exec("rollback;") } - private static async createTables(db: Database){ + private static async createTables(db: Database) { await this.beginTransaction(db); - try{ - await db.exec(`create table if not exists Airport ( - icao TEXT NOT NULL, - name TEXT NOT NULL, - country TEXT NOT NULL, - runwayLength TEXT NOT NULL, - CONSTRAINT pk_airport PRIMARY KEY (icao) - )`); + try { + await db.exec(`create table if not exists Airport + ( + icao TEXT NOT NULL, + name TEXT NOT NULL, + country TEXT NOT NULL, + runwayLength TEXT NOT NULL, + CONSTRAINT pk_airport PRIMARY KEY (icao) + )`); await db.exec(`create table if not exists Plane - ( - tailNo Text Not Null, - model Text not null, - manufacturer text not null, - capacity int not null, - constraint pk_plane primary key (tailNo) - );`) + ( + tailNo Text Not Null, + model Text not null, + manufacturer text not null, + capacity int not null, + constraint pk_plane primary key (tailNo) + );`) await db.exec(`create table if not exists Flight -( - flightNo TEXT not null , - departure text not null, - arrival text, - operates Text not null, - departs text not null, - arrives text not null, - constraint pk_plane primary key (flightNo), - constraint fk_arrives foreign key (arrives) references Airport (icao), - constraint fk_departs foreign key (arrives) references Airport (icao) -);`); + ( + flightNo TEXT not null, + departure text not null, + arrival text, + operates Text not null, + departs text not null, + arrives text not null, + constraint pk_plane primary key (flightNo), + constraint fk_arrives foreign key (arrives) references Airport (icao), + constraint fk_departs foreign key (arrives) references Airport (icao) + );`); await db.exec(` create table if not exists Passenger -( - ssn TEXT not null, - name TEXT not null, - dateOfBirth text not null, - isFemale boolean, + ( + ssn TEXT not null, + name TEXT not null, + dateOfBirth text not null, + isFemale boolean, - constraint pk_passenger primary key (ssn) -); -`); + constraint pk_passenger primary key (ssn) + ); + `); await db.exec(`create table if not exists Reservation - ( - ticketNo INTEGER not null primary key autoincrement, - seat TEXT not null, - flight TEXT not null, - passenger TEXT not null, - constraint fk_flight foreign key (flight) references Flight (flightNo), - constraint fk_passenger foreign key (passenger) references Passenger (ssn) - );`); + ( + ticketNo INTEGER not null primary key autoincrement, + seat TEXT not null, + flight TEXT not null, + passenger TEXT not null, + constraint fk_flight foreign key (flight) references Flight (flightNo), + constraint fk_passenger foreign key (passenger) references Passenger (ssn) + );`); await this.commitTransaction(db); - } - - catch (error){ + } catch (error) { console.error(error); await this.rollbackTransaction(db) } } - private static async addDefaultDataIfNeeded(db : Database) - { + private static async addDefaultDataIfNeeded(db: Database) { const planeCount = await db.get('select count(*) num from Plane;') const airportCount = await db.get('select count(*) num from Airport;') - if(planeCount.num === undefined || planeCount.num === 0) - { + if (planeCount.num === undefined || planeCount.num === 0) { await this.addDefaultPlanes(db); } - if( airportCount.num === undefined || airportCount.num === 0) - { + if (airportCount.num === undefined || airportCount.num === 0) { await this.addDefaultAirports(db); } @@ -110,7 +106,6 @@ export class DB { private static async addDefaultPlanes(db: Database) { - const planes: PlaneModel[] = [ new PlaneModel("OE-LAA", "A320 Neo", "Airbus", 164), new PlaneModel("OE-LAB", "B737-800", "Boeing", 188), diff --git a/src/models/flight.model.ts b/src/models/flight.model.ts index 20b1476..472a9f2 100644 --- a/src/models/flight.model.ts +++ b/src/models/flight.model.ts @@ -1,16 +1,16 @@ -import {PlaneModel} from "./plane.model"; -import {AirportModel} from "./airport.model"; -export class FlightModel { +import {isNullOrUndefined} from "../utility"; + +export class FlightModel{ public flightNo : string; public departure : Date; - public departs : AirportModel; - public arrives : AirportModel; + public departs : string; + public arrives : string; public arrival : Date | null; - public operates : PlaneModel; + public operates : string; - constructor(flightNo: string, operates: PlaneModel, departs: AirportModel, arrives : AirportModel, + constructor(flightNo: string, operates: string, departs: string, arrives : string, departure: Date, arrival: Date | null = null) { this.flightNo = flightNo; this.departure = departure; @@ -19,4 +19,17 @@ export class FlightModel { this.arrival = arrival; this.operates = operates; } -} \ No newline at end of file + + + // check the loical validaity of the flight model + static isValid(element : FlightModel): boolean { + return !isNullOrUndefined(element.flightNo) && + !isNullOrUndefined(element.departure) && + !isNullOrUndefined(element.departs) && + !isNullOrUndefined(element.arrives) && + !isNullOrUndefined(element.operates) && + element.departure.getTime() > Date.now(); + } +} + + diff --git a/src/routes/flight.router.ts b/src/routes/flight.router.ts index a1ac964..83a2080 100644 --- a/src/routes/flight.router.ts +++ b/src/routes/flight.router.ts @@ -1,12 +1,50 @@ - import express, {Request, Response} from "express"; -import {Unit} from "../database/unit"; +import {FlightModel} from "../models/flight.model"; +import {StatusCodes} from "http-status-codes"; +import {getDate, isNullOrUndefined} from "../utility"; +import {AirportService} from "../services/airport.service"; +import {PlaneService} from "../services/plane.service"; +import {FlightService} from "../services/flight.service"; const router = express.Router(); -router.get('/', async (req : Request , res:Response) : Promise => { - await Unit.create(true); - res.sendStatus(200); +router.put('/:flightNo', async (req : Request<{flightNo: string}, FlightModel>, res : Response) : Promise => { + const flightNo : string = req.params.flightNo; + const flight: FlightModel = req.body; + + const departureDate = getDate(flight.departure); + const arrivalDate = flight.arrival === null ? { date : flight.arrival, isValid : true} : getDate(flight.arrival); + + if(!departureDate.isValid || !arrivalDate.isValid || departureDate.date === null) + { + res.sendStatus(StatusCodes.BAD_REQUEST); + return; + } + + flight.arrival = arrivalDate.date; + flight.departure = departureDate.date; + flight.flightNo = flightNo; + + + if(FlightModel.isValid(flight)) + { + res.sendStatus(StatusCodes.BAD_REQUEST); + return; + } + + const arrivalAirport = await AirportService.getOne(flight.arrives) + const departureAirport = await AirportService.getOne(flight.departs) + const plane = await PlaneService.getOne(flight.operates); + + if(isNullOrUndefined(arrivalAirport) || isNullOrUndefined(departureAirport) || isNullOrUndefined(plane)) + { + res.sendStatus(StatusCodes.BAD_REQUEST); + return; + } + + + await FlightService.updateOrCreate(flight); + res.sendStatus(StatusCodes.OK); }) export default router; \ No newline at end of file diff --git a/src/routes/passenger.router.ts b/src/routes/passenger.router.ts index 33ca171..2c55c31 100644 --- a/src/routes/passenger.router.ts +++ b/src/routes/passenger.router.ts @@ -2,6 +2,7 @@ import express, {Request, Response, Router} from "express"; import {PassengerModel} from "../models/passenger.model"; import {StatusCodes} from "http-status-codes"; import {PassengerService} from "../services/passenger.service"; +import {getDate} from "../utility"; const router: Router = express.Router(); @@ -10,14 +11,13 @@ router.put('/:ssn', async (request: Request<{ ssn: string }, PassengerModel>, re const ssn: string = request.params.ssn; const passenger: PassengerModel = request.body; - if (typeof passenger.dateOfBirth === "string") { //warning because of type loss at run time - passenger.dateOfBirth = new Date(Date.parse(passenger.dateOfBirth)); - } + const returnType = getDate(passenger.dateOfBirth) - if (ssn === undefined || ssn.length != 9) { + if ( !returnType.isValid || returnType.date === null || ssn === undefined || ssn.length != 9) { response.sendStatus(StatusCodes.BAD_REQUEST); return; } + passenger.dateOfBirth = returnType.date; passenger.ssn = ssn; await PassengerService.updateOrCreate(passenger) diff --git a/src/services/flight.service.ts b/src/services/flight.service.ts new file mode 100644 index 0000000..a7ef7bd --- /dev/null +++ b/src/services/flight.service.ts @@ -0,0 +1,54 @@ + +import {ServiceBase} from "./serviceBase"; +import {FlightModel} from "../models/flight.model"; + +export class FlightService extends ServiceBase { + static async getOne(flightNo : string) : Promise{ + const sql = `select flightNo, departure, arrival, operates, departs, arrives from Flight where flightNo = ?1` + const params = { + 1: flightNo + } + return await this.get(sql, params); + } + + static async create(flight: FlightModel): Promise { + const sql = `insert into Flight (flightNo, departure, arrival, operates, departs, arrives) VALUES + (?1, ?2, ?3, ?4, ?5, ?6)`; + const params = { + 1: flight.flightNo, + 2: flight.departure.toISOString(), + 3: flight.arrival === null ? null : flight.arrival.toISOString(), + 4: flight.operates, + 5: flight.departs, + 6: flight.arrives + + }; + return await this.run(sql, params, 1); + } + + + static async update(flight: FlightModel): Promise { + const sql = `UPDATE Flight SET departure = ?1, arrival = ?2, operates = ?3, departs = ?4, arrives = ?5 WHERE flightNo = ?6`; + const params = { + 1: flight.departure.toISOString(), + 2: flight.arrival === null ? null : flight.arrival.toISOString(), + 3: flight.operates, + 4: flight.departs, + 5: flight.arrives, + 6: flight.flightNo + }; + + return await this.run(sql, params, 1); + } + + static async updateOrCreate(flightModel : FlightModel) : Promise{ + const dbPassenger = await this.getOne(flightModel.flightNo); + if(dbPassenger === null) + { + await this.create(flightModel); + } + else{ + await this.update(flightModel); + } + } +} \ No newline at end of file diff --git a/src/services/plane.service.ts b/src/services/plane.service.ts index 44093d1..2f04b46 100644 --- a/src/services/plane.service.ts +++ b/src/services/plane.service.ts @@ -28,5 +28,4 @@ export class PlaneService extends ServiceBase { return await this.all(sql, params); } - } \ No newline at end of file diff --git a/src/utility.ts b/src/utility.ts new file mode 100644 index 0000000..d532771 --- /dev/null +++ b/src/utility.ts @@ -0,0 +1,18 @@ +export function isNullOrUndefined(element : any) +{ + return element === undefined || element === null +} + +export function getDate(date : Date | string) : {date: Date | null, isValid: boolean} { + if (typeof date === "string") { //warning because of type loss at run time + + const dateNum = Date.parse(date); + + if(Number.isNaN(dateNum)){ + return {date: null,isValid: true}; + } + + return {date: new Date(dateNum),isValid: true}; + } + return {date: date,isValid: true}; +} \ No newline at end of file