From 20eb2cfdc11498fac230516f73fd0cca1296f6d1 Mon Sep 17 00:00:00 2001 From: vab5 Date: Sat, 24 Feb 2024 22:28:01 -0600 Subject: [PATCH 1/5] first commit --- src/controllers/Passenger.controller.ts | 180 ++++++++++++++++++++---- src/routes/routes.ts | 2 +- 2 files changed, 153 insertions(+), 29 deletions(-) diff --git a/src/controllers/Passenger.controller.ts b/src/controllers/Passenger.controller.ts index 0ff316a..f9c366c 100644 --- a/src/controllers/Passenger.controller.ts +++ b/src/controllers/Passenger.controller.ts @@ -13,6 +13,8 @@ const base = new Airtable({ apiKey: process.env.AIRTABLE_API_KEY || '', }).base('appwPsfAb6U8CV3mf'); +const Joi = require('joi'); + /** * Get all of the related passengers for a user (people they have flown with in the past) * @@ -94,46 +96,168 @@ export const getPassengerById = async (req: Request, res: Response) => { * 2. Get the passenger data from the request body, if it doesn't exist return a 400 * 3. Make a call to AirTable to create the passenger, if that fails return a 500 (hint, use try/catch) * 4. Return the created passenger + * 5. add the passenger to the accompanying passengers of the user (req.params) sending the request * * @param req - the request object * @param res - the response object */ + export const createPassenger = async (req: Request, res: Response) => { - const userId = req.query.userId; + //gets userId and passengerData from parameters + const { id } = req.params; const passengerData = req.body; - if (!userId) { - return res.status(400).send({ error: 'User ID is required' }); + if (!id) { + return res.status(400).send('AirTable Record ID is required'); } + if (!passengerData) { - return res.status(400).send({ error: 'Passenger data is required' }); + return res.status(400).send('Passenger data is required.'); + } + try { + const passenger = await base('Passengers').find(id); + } catch (err: any) { + return res.status(400).send('User does not exist'); + } + + //joi stuff to validate whether the passengerData is of the right format + + const passengerSchema = Joi.object({ + fields: Joi.object({ + Relationship: Joi.string() + .valid( + 'Mother', + 'Father', + 'Step-mother', + 'Step-father', + 'Legal Guardian', + 'Spouse', + 'Family Member', + 'Other Caregiver' + ) + .required(), + 'First Name': Joi.string().required(), + 'Last Name': Joi.string().required(), + 'Date of Birth': Joi.date().required(), + Diagnoses: Joi.array().items(Joi.string()), + Gender: Joi.string().valid('Male', 'Female', 'Other').required(), + Street: Joi.string().required(), + City: Joi.string().required(), + State: Joi.string().required(), + Zip: Joi.string().required(), + Country: Joi.string().required(), + 'Cell Phone': Joi.string() + .regex(/^\(\d{3}\) \d{3}-\d{4}$/) + .required(), + Email: Joi.string().email().required(), + Waiver: Joi.boolean().required(), + }).required(), + }); + + const { error, value } = passengerSchema.validate(passengerData); + + if (error) { + console.log(error.details); + return res.status(400).send(error.details); + } else { + console.log('Validation successful', value); } - const newRecord = { - fields: { - 'First Name': passengerData.firstName, - 'Middle Name': passengerData.middleName || '', - 'Last Name': passengerData.lastName, - Email: passengerData.email, - Type: passengerData.type, - '# of Booked Flight Requests': passengerData.numBookedFlightRequests, - 'Multi-patient family?': passengerData.multiPatientFamily, - Relationship: passengerData.relationship, - Birthday: passengerData.birthday, - 'Day Before Birthday': passengerData.dayBeforeBirthday, - 'Day After Birthday': passengerData.dayAfterBirthday, - - UserId: userId, - }, - typecast: true, - }; try { - // const createdRecords = await base('Passengers').create([newRecord]); - // const createdPassenger = createdRecords[0]; - // res.status(200).send({ createdPassenger }); - } catch (error) { - logger.info(error); - res.status(500).send({ error: 'Failed to create passenger' }); + const createdPassenger = await base('Passengers').create( + [ + { + fields: { + Type: 'Accompanying Passenger', + Relationship: passengerData.relationship, + 'First Name': passengerData.firstName, + 'Last Name': passengerData.lastName, + 'Date of Birth': passengerData.birthday, + Diagnoses: [], + Gender: passengerData.Gender, + Street: passengerData.Street, + City: passengerData.City, + State: passengerData.State, + Zip: passengerData.Zip, + Country: passengerData.Country, + 'Cell Phone': passengerData.Cell, + Email: passengerData.Email, + Waiver: passengerData.Waiver, + 'All Flight Requests (Pass 2)': [], + 'All Flight Legs': [], + 'Related Patient(s)': [], + }, + }, + ], + function (err, records) { + if (err) { + console.error(err); + return res.status(500).json({ error: 'Error creating passenger' }); + } + // records.forEach(function (record) { + // console.log(record.getId()); + // }); + } + ); + + try { + // var previousRecords; + // const user = await base('Passengers').find(id, function(err, record) { + // if (err) { console.error(err); return; } + // console.log('Retrieved', record?.id); + // previousRecords = record?.fields["Related Accompanying Passenger(s)"]; + // }); + // const userRecord = await base('Passengers').find(id); + // let previousRecords = userRecord.fields["Related Accompanying Passenger(s)"] || []; + // previousRecords.push(createdPassenger.id); // Use the ID of the created passenger + + // await base('Passengers').update([ + // { "id": id, "fields": { "Related Accompanying Passenger(s)": previousRecords }}, + // ]); + + //need to get the related accompanying passengers of the user + + // await base('Passengers').update([ + // { + // "id": id, + // "fields": { + // "Related Accompanying Passenger(s)": previousRecords.push(createdPassenger) + // } + // } + + // ], function(err, records) { + // if (err) { + // console.error(err); + // return; + // } + // }); + + const userRecord = await base('Passengers').find(id); + + let relatedPassengers = + userRecord.fields['Related Accompanying Passenger(s)']; + if (!relatedPassengers) { + relatedPassengers = []; + } + + // Assuming you want to add a simple string like "John Doe" to the list + const passengerName = `${passengerData['First Name']} ${passengerData['Last Name']}`; + //relatedPassengers.push(passengerName); + relatedPassengers = relatedPassengers + passengerName; + + // Update the user record with the new list of related passengers + await base('Passengers').update(id, { + 'Related Accompanying Passenger(s)': relatedPassengers, + }); + } catch (err2: any) { + console.error(err2); + return res.status(500).json({ error: 'Error updating user' }); + } + + return createdPassenger; + } catch (err: any) { + console.error(err); + return res.status(500).json({ error: 'Error creating passenger' }); } }; diff --git a/src/routes/routes.ts b/src/routes/routes.ts index 20fc663..6682241 100644 --- a/src/routes/routes.ts +++ b/src/routes/routes.ts @@ -34,7 +34,7 @@ const routes = (app: Express) => { /* Passenger Controller Routes */ app.get('/passenger/', getAllPassengersForUser); app.get('/passenger/:id', getPassengerById); - app.post('/passenger/', createPassenger); + app.post('/passenger/:id', createPassenger); app.put('/passenger/:id', updatePassenger); /* Flight Request Controller Routes */ From 158c75544778e132218ca35f37ca3f9912527ac3 Mon Sep 17 00:00:00 2001 From: vab5 Date: Sat, 24 Feb 2024 22:53:39 -0600 Subject: [PATCH 2/5] more errors --- src/controllers/Passenger.controller.ts | 29 ++++++++++++------------- 1 file changed, 14 insertions(+), 15 deletions(-) diff --git a/src/controllers/Passenger.controller.ts b/src/controllers/Passenger.controller.ts index f9c366c..9f31a24 100644 --- a/src/controllers/Passenger.controller.ts +++ b/src/controllers/Passenger.controller.ts @@ -169,20 +169,20 @@ export const createPassenger = async (req: Request, res: Response) => { { fields: { Type: 'Accompanying Passenger', - Relationship: passengerData.relationship, - 'First Name': passengerData.firstName, - 'Last Name': passengerData.lastName, - 'Date of Birth': passengerData.birthday, - Diagnoses: [], - Gender: passengerData.Gender, - Street: passengerData.Street, - City: passengerData.City, - State: passengerData.State, - Zip: passengerData.Zip, - Country: passengerData.Country, - 'Cell Phone': passengerData.Cell, - Email: passengerData.Email, - Waiver: passengerData.Waiver, + Relationship: passengerData.fields.Relationship, + 'First Name': passengerData.fields['First Name'], + 'Last Name': passengerData.fields['Last Name'], + 'Date of Birth': passengerData.fields['Date of Birth'], + Diagnoses: passengerData.fields.Diagnoses || [], + Gender: passengerData.fields.Gender, + Street: passengerData.fields.Street, + City: passengerData.fields.City, + State: passengerData.fields.State, + Zip: passengerData.fields.Zip, + Country: passengerData.fields.Country, + 'Cell Phone': passengerData.fields['Cell Phone'], + Email: passengerData.fields.Email, + Waiver: passengerData.fields.Waiver, 'All Flight Requests (Pass 2)': [], 'All Flight Legs': [], 'Related Patient(s)': [], @@ -240,7 +240,6 @@ export const createPassenger = async (req: Request, res: Response) => { relatedPassengers = []; } - // Assuming you want to add a simple string like "John Doe" to the list const passengerName = `${passengerData['First Name']} ${passengerData['Last Name']}`; //relatedPassengers.push(passengerName); relatedPassengers = relatedPassengers + passengerName; From f9cf8aac39d193b6b075b17242e7df42aa6a5201 Mon Sep 17 00:00:00 2001 From: vab5 Date: Wed, 28 Feb 2024 19:14:14 -0600 Subject: [PATCH 3/5] should be done. need to test. --- src/controllers/Passenger.controller.ts | 100 ++++++++++-------------- 1 file changed, 40 insertions(+), 60 deletions(-) diff --git a/src/controllers/Passenger.controller.ts b/src/controllers/Passenger.controller.ts index 9f31a24..c852d86 100644 --- a/src/controllers/Passenger.controller.ts +++ b/src/controllers/Passenger.controller.ts @@ -163,8 +163,9 @@ export const createPassenger = async (req: Request, res: Response) => { console.log('Validation successful', value); } + //if validation is successful try to create the passenger try { - const createdPassenger = await base('Passengers').create( + await base('Passengers').create( [ { fields: { @@ -189,71 +190,50 @@ export const createPassenger = async (req: Request, res: Response) => { }, }, ], - function (err, records) { + async (err, records) => { if (err) { console.error(err); return res.status(500).json({ error: 'Error creating passenger' }); } - // records.forEach(function (record) { - // console.log(record.getId()); - // }); - } - ); - - try { - // var previousRecords; - // const user = await base('Passengers').find(id, function(err, record) { - // if (err) { console.error(err); return; } - // console.log('Retrieved', record?.id); - // previousRecords = record?.fields["Related Accompanying Passenger(s)"]; - // }); - // const userRecord = await base('Passengers').find(id); - // let previousRecords = userRecord.fields["Related Accompanying Passenger(s)"] || []; - // previousRecords.push(createdPassenger.id); // Use the ID of the created passenger - - // await base('Passengers').update([ - // { "id": id, "fields": { "Related Accompanying Passenger(s)": previousRecords }}, - // ]); - - //need to get the related accompanying passengers of the user - - // await base('Passengers').update([ - // { - // "id": id, - // "fields": { - // "Related Accompanying Passenger(s)": previousRecords.push(createdPassenger) - // } - // } - - // ], function(err, records) { - // if (err) { - // console.error(err); - // return; - // } - // }); - const userRecord = await base('Passengers').find(id); - - let relatedPassengers = - userRecord.fields['Related Accompanying Passenger(s)']; - if (!relatedPassengers) { - relatedPassengers = []; + //passenger was created successfully, we need to add them to the relatedPassenger of the user + try { + let relatedPassengers = [] as string[]; + + //find the current related passengers of the user id + base('Passengers').find(id, async (err, record) => { + if (err) { + console.error(err); + return; + } + console.log('Retrieved', record?.id); + + relatedPassengers = record?.fields[ + 'Related Accompanying Passenger(s)' + ] as string[]; + + console.log(relatedPassengers); + + //add the passenger we just created to the user's previous related passengers + const newRelatedPassengers = [ + ...(relatedPassengers || []), + records?.[0].id, + ]; + console.log(newRelatedPassengers); + + // Update the user record with the new list of related passengers + await base('Passengers').update(id, { + 'Related Accompanying Passenger(s)': newRelatedPassengers, + }); + + return res.status(200).send(trimPassenger(records?.[0]._rawJson)); + }); + } catch (err2: any) { + console.error(err2); + return res.status(500).json({ error: 'Error updating user' }); + } } - - const passengerName = `${passengerData['First Name']} ${passengerData['Last Name']}`; - //relatedPassengers.push(passengerName); - relatedPassengers = relatedPassengers + passengerName; - - // Update the user record with the new list of related passengers - await base('Passengers').update(id, { - 'Related Accompanying Passenger(s)': relatedPassengers, - }); - } catch (err2: any) { - console.error(err2); - return res.status(500).json({ error: 'Error updating user' }); - } - - return createdPassenger; + ); } catch (err: any) { console.error(err); return res.status(500).json({ error: 'Error creating passenger' }); From c07a73b77596d0dd90811b10cf67e51c4d26003f Mon Sep 17 00:00:00 2001 From: vab5 Date: Wed, 28 Feb 2024 19:16:53 -0600 Subject: [PATCH 4/5] Fix imports --- src/controllers/Passenger.controller.ts | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/src/controllers/Passenger.controller.ts b/src/controllers/Passenger.controller.ts index c852d86..de3b2c4 100644 --- a/src/controllers/Passenger.controller.ts +++ b/src/controllers/Passenger.controller.ts @@ -7,14 +7,13 @@ import type { Request, Response } from 'express'; import Airtable from 'airtable'; import dotenv from 'dotenv'; import type { FieldSet, Record } from 'airtable'; +import Joi from 'joi'; dotenv.config(); const base = new Airtable({ apiKey: process.env.AIRTABLE_API_KEY || '', }).base('appwPsfAb6U8CV3mf'); -const Joi = require('joi'); - /** * Get all of the related passengers for a user (people they have flown with in the past) * From e914906bf6a333b821326d530bfe0901c4af2bf9 Mon Sep 17 00:00:00 2001 From: vab5 Date: Wed, 20 Mar 2024 17:41:41 -0500 Subject: [PATCH 5/5] should be done with create passenger endpoint --- src/controllers/Passenger.controller.ts | 10 +-- src/tests/Passenger.tests.ts | 89 ++++++++++++++++++++++++- 2 files changed, 89 insertions(+), 10 deletions(-) diff --git a/src/controllers/Passenger.controller.ts b/src/controllers/Passenger.controller.ts index de3b2c4..b8ad1c3 100644 --- a/src/controllers/Passenger.controller.ts +++ b/src/controllers/Passenger.controller.ts @@ -156,12 +156,8 @@ export const createPassenger = async (req: Request, res: Response) => { const { error, value } = passengerSchema.validate(passengerData); if (error) { - console.log(error.details); - return res.status(400).send(error.details); - } else { - console.log('Validation successful', value); + return res.status(400).json(error.details); } - //if validation is successful try to create the passenger try { await base('Passengers').create( @@ -205,20 +201,16 @@ export const createPassenger = async (req: Request, res: Response) => { console.error(err); return; } - console.log('Retrieved', record?.id); relatedPassengers = record?.fields[ 'Related Accompanying Passenger(s)' ] as string[]; - console.log(relatedPassengers); - //add the passenger we just created to the user's previous related passengers const newRelatedPassengers = [ ...(relatedPassengers || []), records?.[0].id, ]; - console.log(newRelatedPassengers); // Update the user record with the new list of related passengers await base('Passengers').update(id, { diff --git a/src/tests/Passenger.tests.ts b/src/tests/Passenger.tests.ts index fc3a1be..bc4f87a 100644 --- a/src/tests/Passenger.tests.ts +++ b/src/tests/Passenger.tests.ts @@ -46,7 +46,11 @@ describe('GET /passenger', () => { .get('/passenger') .query({ id: 'recleNlsBm3dheZHy' }) .end((err, res) => { - expect(res.body[0]['First Name']).to.be.oneOf(['Anakin', 'Bail']); + expect(res.body[0]['First Name']).to.be.oneOf([ + 'Anakin', + 'Bail', + 'Jefferson', + ]); expect(res).to.have.status(200); done(); }); @@ -74,3 +78,86 @@ describe('GET /passenger', () => { }); }); }); + +//Test createPassenger + +describe('POST /createPassenger', () => { + it('should return 400 if userId is not provided', done => { + chai + .request(app) + .post('/passenger/') + .send({}) + .end((err, res) => { + expect(res).to.have.status(404); + done(); + }); + }); + + it('should return 400 if passenger data is not provided', done => { + chai + .request(app) + .post('/passenger/rec3Wv1VViXYv3t72') + .send({ id: 'rec3Wv1VViXYv3t72' }) + .end((err, res) => { + expect(res).to.have.status(400); + expect(res.body[0].message).to.equal('"fields" is required'); + done(); + }); + }); + + it('should return 400 if user does not exist in AirTable', done => { + chai + .request(app) + .post('/passenger/thisIsBad') + .send({ + fields: { + Relationship: 'Father', + 'First Name': 'Testman', + 'Last Name': 'tester', + 'Date of Birth': '1989-01-05', + Gender: 'Male', + Street: '123 Main St', + City: 'Anytown', + State: 'TN', + Zip: '12345', + Country: 'United States', + 'Cell Phone': '(123) 456-7890', + Email: 'jane.doe@example.com', + Waiver: true, + }, + }) + .end((err, res) => { + expect(res).to.have.status(400); + expect(res.text).to.contain('User does not exist'); + done(); + }); + }); + + it('should return 200 and create a passenger when provided valid data', done => { + chai + .request(app) + .post('/passenger/rec3Wv1VViXYv3t72') + .send({ + fields: { + Relationship: 'Father', + 'First Name': 'Testman', + 'Last Name': 'tester', + 'Date of Birth': '1989-01-05', + Gender: 'Male', + Street: '123 Main St', + City: 'Anytown', + State: 'TN', + Zip: '12345', + Country: 'United States', + 'Cell Phone': '(123) 456-7890', + Email: 'jane.doe@example.com', + Waiver: true, + }, + }) + .end((err, res) => { + expect(res).to.have.status(200); + expect(res.body['First Name']).to.be.oneOf(['Testman']); + done(); + }); + }); +});