done with timeSlots lookup
This commit is contained in:
parent
fee7f1a266
commit
53dd3ada4f
9 changed files with 193 additions and 56 deletions
24
README.md
24
README.md
|
@ -18,6 +18,30 @@ install pg MacOS -
|
||||||
Start Postgres -
|
Start Postgres -
|
||||||
brew services start postgresql
|
brew services start postgresql
|
||||||
|
|
||||||
|
Postgres CLI -
|
||||||
|
psql postgres
|
||||||
|
|
||||||
|
init POSTGRES Database -
|
||||||
|
CREATE DATABASE drop_shopping;
|
||||||
|
|
||||||
|
create tables -
|
||||||
|
timeSlots -
|
||||||
|
CREATE TABLE time_slots (
|
||||||
|
id SERIAL PRIMARY KEY,
|
||||||
|
start_time TIME NOT NULL,
|
||||||
|
end_time TIME NOT NULL,
|
||||||
|
created_at TIMESTAMP DEFAULT NOW(),
|
||||||
|
updated_at TIMESTAMP DEFAULT NOW()
|
||||||
|
);
|
||||||
|
|
||||||
|
holidays -
|
||||||
|
CREATE TABLE holidays (
|
||||||
|
id SERIAL PRIMARY KEY,
|
||||||
|
holiday_date DATE NOT NULL,
|
||||||
|
created_at TIMESTAMP DEFAULT NOW(),
|
||||||
|
updated_at TIMESTAMP DEFAULT NOW()
|
||||||
|
);
|
||||||
|
|
||||||
|
|
||||||
knex for migration files
|
knex for migration files
|
||||||
npx knex migrate:make create_addresses_table
|
npx knex migrate:make create_addresses_table
|
||||||
|
|
|
@ -1,7 +1,17 @@
|
||||||
{
|
[
|
||||||
"holidays": [
|
{
|
||||||
"2023-05-01",
|
"name": "New Year's Day",
|
||||||
"2023-06-12",
|
"date": "2023-01-17",
|
||||||
"2023-09-25"
|
"country": "US"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "Mother's Day",
|
||||||
|
"date": "2023-09-18",
|
||||||
|
"country": "US"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "Independence Day",
|
||||||
|
"date": "2023-09-17",
|
||||||
|
"country": "GB"
|
||||||
|
}
|
||||||
]
|
]
|
||||||
}
|
|
|
@ -1,10 +1,39 @@
|
||||||
{
|
{
|
||||||
"timeSlots": [
|
"courier_available_timeslots": [
|
||||||
"08:00 - 10:00",
|
{
|
||||||
"10:00 - 12:00",
|
"start_time": "2023-09-17 08:00:00",
|
||||||
"12:00 - 14:00",
|
"end_time": "2023-09-17 09:00:00",
|
||||||
"14:00 - 16:00",
|
"supported_postcodes": [
|
||||||
"16:00 - 18:00",
|
"W1H 1LJ",
|
||||||
"18:00 - 20:00"
|
"2222222"
|
||||||
|
]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"start_time": "2023-09-17 09:00:00",
|
||||||
|
"end_time": "2023-09-17 10:00:00",
|
||||||
|
"supported_postcodes": [
|
||||||
|
"1111111",
|
||||||
|
"2222222",
|
||||||
|
"3333333"
|
||||||
|
]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"start_time": "2023-09-17 09:00:00",
|
||||||
|
"end_time": "2023-09-17 10:00:00",
|
||||||
|
"supported_postcodes": [
|
||||||
|
"4444444",
|
||||||
|
"5555555",
|
||||||
|
"6666666"
|
||||||
|
]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"start_time": "2023-09-18 14:00:00",
|
||||||
|
"end_time": "2023-09-18 15:00:00",
|
||||||
|
"supported_postcodes": [
|
||||||
|
"W1H 1LJ",
|
||||||
|
"5555555",
|
||||||
|
"6666666"
|
||||||
|
]
|
||||||
|
}
|
||||||
]
|
]
|
||||||
}
|
}
|
|
@ -13,12 +13,14 @@ export const resolveAddress = async (searchTerm: string): Promise<Address> => {
|
||||||
const response = await axios.get(`https://api.geoapify.com/v1/geocode/search?text=${searchTerm}&format=json&apiKey=${GEOCODING_API_KEY}`);
|
const response = await axios.get(`https://api.geoapify.com/v1/geocode/search?text=${searchTerm}&format=json&apiKey=${GEOCODING_API_KEY}`);
|
||||||
if (response.data.results.length > 0) {
|
if (response.data.results.length > 0) {
|
||||||
const result = response.data.results[0];
|
const result = response.data.results[0];
|
||||||
|
console.log(result)
|
||||||
return {
|
return {
|
||||||
country: result.country,
|
country: result.country,
|
||||||
street: result.street,
|
street: result.street,
|
||||||
line1: result.address_line1,
|
line1: result.address_line1,
|
||||||
line2: result.address_line2,
|
line2: result.address_line2,
|
||||||
postcode: result.postcode
|
postcode: result.postcode,
|
||||||
|
code: result.country_code.toUpperCase()
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
throw new Error('No results found');
|
throw new Error('No results found');
|
||||||
|
|
|
@ -1,12 +1,16 @@
|
||||||
import { Request, Response } from 'express';
|
import { Request, Response } from 'express';
|
||||||
import { resolveAddress } from './geocoding';
|
import { resolveAddress } from './geocoding';
|
||||||
import { Address } from './types';
|
import { Address, AvailableTimeslots } from './types';
|
||||||
// DOME
|
// DOME
|
||||||
import { getAvailableTimeSlots } from './services/timeslotsService';
|
import { getAvailableTimeSlots } from './services/timeslotsService';
|
||||||
import { getHolidays } from './services/holidaysService';
|
import { getHolidays } from './services/holidaysService';
|
||||||
|
|
||||||
export const resolveAddressHandler = (req: Request, res: Response) => {
|
export const resolveAddressHandler = (req: Request, res: Response) => {
|
||||||
console.info("resolveAddressHandler called");
|
console.info("resolveAddressHandler called");
|
||||||
|
if (!req.body.searchTerm) {
|
||||||
|
res.status(400).json({ error: 'Missing searchTerm' });
|
||||||
|
return;
|
||||||
|
}
|
||||||
const address: Promise<Address> = resolveAddress(req.body.searchTerm);
|
const address: Promise<Address> = resolveAddress(req.body.searchTerm);
|
||||||
address.then((result) => {
|
address.then((result) => {
|
||||||
console.info("resolveAddressHandler result: ", result);
|
console.info("resolveAddressHandler result: ", result);
|
||||||
|
@ -14,10 +18,16 @@ export const resolveAddressHandler = (req: Request, res: Response) => {
|
||||||
})
|
})
|
||||||
};
|
};
|
||||||
|
|
||||||
export const timeslotsHandler = (req: Request, res: Response) => {
|
export const timeslotsHandler = async (req: Request, res: Response) => {
|
||||||
// TODO: Implement timeslots functionality
|
// TODO: Implement timeslots functionality
|
||||||
|
if (!req.body.address) {
|
||||||
|
res.status(400).json({ error: 'Missing address' });
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
const address: Address = req.body.address;
|
||||||
|
const timeSlots: AvailableTimeslots[] = await availableTimeSlots(address);
|
||||||
|
const availableTimeSlotsResult = await filterOutHolidaysByCountryCode(address, timeSlots);
|
||||||
|
res.status(200).json(availableTimeSlotsResult);
|
||||||
};
|
};
|
||||||
|
|
||||||
export const deliveriesHandler = (req: Request, res: Response) => {
|
export const deliveriesHandler = (req: Request, res: Response) => {
|
||||||
|
@ -35,3 +45,41 @@ export const dailyDeliveriesHandler = (req: Request, res: Response) => {
|
||||||
export const weeklyDeliveriesHandler = (req: Request, res: Response) => {
|
export const weeklyDeliveriesHandler = (req: Request, res: Response) => {
|
||||||
// TODO: Implement weekly deliveries functionality
|
// TODO: Implement weekly deliveries functionality
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
async function filterOutHolidaysByCountryCode(address: Address, availableTimeSlot: AvailableTimeslots[]) {
|
||||||
|
const countryCode = address.code;
|
||||||
|
const holidays = await getHolidays();
|
||||||
|
|
||||||
|
const filteredAvailableTimeSlot = [];
|
||||||
|
|
||||||
|
|
||||||
|
console.log(availableTimeSlot)
|
||||||
|
holidays.forEach((holiday) => {
|
||||||
|
if(holiday.country === countryCode) {
|
||||||
|
availableTimeSlot.forEach((timeSlot) => {
|
||||||
|
if(timeSlot.start_time.split(' ')[0] !== holiday.date) {
|
||||||
|
filteredAvailableTimeSlot.push(timeSlot)
|
||||||
|
}
|
||||||
|
})
|
||||||
|
}
|
||||||
|
});
|
||||||
|
return filteredAvailableTimeSlot;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
async function availableTimeSlots(address: Address) {
|
||||||
|
const availableTimeSlot = [];
|
||||||
|
const timeslots = await getAvailableTimeSlots();
|
||||||
|
// check by postcode if any available timeslots
|
||||||
|
for (const timeslot of timeslots.courier_available_timeslots) {
|
||||||
|
if (timeslot.supported_postcodes.includes(address.postcode)) {
|
||||||
|
availableTimeSlot.push({
|
||||||
|
start_time: timeslot.start_time,
|
||||||
|
end_time: timeslot.end_time
|
||||||
|
});
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return availableTimeSlot;
|
||||||
|
}
|
70
src/index.ts
70
src/index.ts
|
@ -8,40 +8,52 @@ app.listen(PORT, () => {
|
||||||
console.log("STARTING ... ")
|
console.log("STARTING ... ")
|
||||||
if (env === 'development') {
|
if (env === 'development') {
|
||||||
console.log("Generating mock data files")
|
console.log("Generating mock data files")
|
||||||
generateMockDataFiles();
|
// generateMockDataFiles();
|
||||||
}
|
}
|
||||||
console.log(`Server is running on port ${PORT}`);
|
console.log(`Server is running on port ${PORT}`);
|
||||||
});
|
});
|
||||||
|
|
||||||
|
|
||||||
const generateMockDataFiles = () => {
|
// const generateMockDataFiles = () => {
|
||||||
|
|
||||||
if (!fs.existsSync('./data')) {
|
// if (!fs.existsSync('./data')) {
|
||||||
fs.mkdirSync('./data');
|
// fs.mkdirSync('./data');
|
||||||
}
|
// }
|
||||||
|
|
||||||
if (!fs.existsSync('./data/timeSlots.json')) {
|
// if (!fs.existsSync('./data/timeSlots.json')) {
|
||||||
const timeSlots = {
|
// const timeSlots = {
|
||||||
timeSlots: [
|
// timeSlots: [
|
||||||
"08:00 - 10:00",
|
// "08:00 - 10:00",
|
||||||
"10:00 - 12:00",
|
// "10:00 - 12:00",
|
||||||
"12:00 - 14:00",
|
// "12:00 - 14:00",
|
||||||
"14:00 - 16:00",
|
// "14:00 - 16:00",
|
||||||
"16:00 - 18:00",
|
// "16:00 - 18:00",
|
||||||
"18:00 - 20:00"
|
// "18:00 - 20:00"
|
||||||
]
|
// ]
|
||||||
}
|
// }
|
||||||
fs.writeFileSync('./data/timeSlots.json', JSON.stringify(timeSlots));
|
// fs.writeFileSync('./data/timeSlots.json', JSON.stringify(timeSlots));
|
||||||
}
|
// }
|
||||||
|
|
||||||
if (!fs.existsSync('./data/holidays.json')) {
|
// if (!fs.existsSync('./data/holidays.json')) {
|
||||||
const holidays = {
|
// const holidays = {
|
||||||
holidays: [
|
// "holidays": [
|
||||||
"2023-05-01",
|
// {
|
||||||
"2023-06-12",
|
// "name": "New Year's Day",
|
||||||
"2023-09-25"
|
// "date": "2023-01-17",
|
||||||
]
|
// "country": "US"
|
||||||
}
|
// },
|
||||||
fs.writeFileSync('./data/holidays.json', JSON.stringify(holidays));
|
// {
|
||||||
}
|
// "name": "Mother's Day",
|
||||||
}
|
// "date": "2023-09-18",
|
||||||
|
// "country": "US"
|
||||||
|
// },
|
||||||
|
// {
|
||||||
|
// "name": "Independence Day",
|
||||||
|
// "date": "2023-10-17",
|
||||||
|
// "country": "US"
|
||||||
|
// }
|
||||||
|
// ]
|
||||||
|
// }
|
||||||
|
// fs.writeFileSync('./data/holidays.json', JSON.stringify(holidays));
|
||||||
|
// }
|
||||||
|
// }
|
|
@ -4,9 +4,9 @@ import { resolveAddressHandler, timeslotsHandler, deliveriesHandler, cancelDeliv
|
||||||
const router = express.Router();
|
const router = express.Router();
|
||||||
|
|
||||||
router.post('/resolve-address', resolveAddressHandler);
|
router.post('/resolve-address', resolveAddressHandler);
|
||||||
|
router.post('/timeslots', timeslotsHandler);
|
||||||
router.get('/deliveries/daily', dailyDeliveriesHandler);
|
router.get('/deliveries/daily', dailyDeliveriesHandler);
|
||||||
router.get('/deliveries/weekly', weeklyDeliveriesHandler);
|
router.get('/deliveries/weekly', weeklyDeliveriesHandler);
|
||||||
router.post('/timeslots', timeslotsHandler);
|
|
||||||
router.post('/deliveries', deliveriesHandler);
|
router.post('/deliveries', deliveriesHandler);
|
||||||
router.delete('/deliveries/:id', cancelDeliveryHandler);
|
router.delete('/deliveries/:id', cancelDeliveryHandler);
|
||||||
|
|
||||||
|
|
|
@ -12,9 +12,15 @@ exports.seed = async function(knex) {
|
||||||
const holidays = require('../data/holidays.json');
|
const holidays = require('../data/holidays.json');
|
||||||
const timeslots = require('../data/timeslots.json');
|
const timeslots = require('../data/timeslots.json');
|
||||||
|
|
||||||
|
console.log(holidays)
|
||||||
// Insert the holiday dates into the holidays table
|
// Insert the holiday dates into the holidays table
|
||||||
for (const date of holidays) {
|
for (const date of holidays) {
|
||||||
await knex('holidays').insert({ date });
|
console.log(date)
|
||||||
|
await knex('holidays').insert( {
|
||||||
|
name: "test",
|
||||||
|
date: "2020-12-25",
|
||||||
|
country: "US"
|
||||||
|
} );
|
||||||
}
|
}
|
||||||
|
|
||||||
// Insert the time slots into the timeslots table
|
// Insert the time slots into the timeslots table
|
|
@ -4,4 +4,10 @@ export interface Address {
|
||||||
line2: string;
|
line2: string;
|
||||||
country: string;
|
country: string;
|
||||||
postcode: string;
|
postcode: string;
|
||||||
|
code: string;
|
||||||
|
}
|
||||||
|
|
||||||
|
export interface AvailableTimeslots {
|
||||||
|
start_time: string;
|
||||||
|
end_time: string;
|
||||||
}
|
}
|
Loading…
Reference in a new issue