mirror of
https://github.com/tomru/pfadi-bussle.git
synced 2026-03-03 06:27:11 +01:00
also get booked days from calendar
This commit is contained in:
@@ -5,7 +5,6 @@ import { createCalendarEvent, deleteCalendarEvent } from '../lib/googlecalendar'
|
|||||||
|
|
||||||
import { Bill } from './bill'
|
import { Bill } from './bill'
|
||||||
import { BOOKING_STATUS, VALIDATION_ERRORS } from './enums'
|
import { BOOKING_STATUS, VALIDATION_ERRORS } from './enums'
|
||||||
import { getBookedDays } from './index'
|
|
||||||
|
|
||||||
export type Booking = {
|
export type Booking = {
|
||||||
uuid: string
|
uuid: string
|
||||||
@@ -76,7 +75,7 @@ const BookingSchema = new mongoose.Schema<BookingDocument>(
|
|||||||
validator: async function (days: string[]): Promise<boolean> {
|
validator: async function (days: string[]): Promise<boolean> {
|
||||||
const booking = this as Booking
|
const booking = this as Booking
|
||||||
const uuid = booking.uuid && [booking.uuid]
|
const uuid = booking.uuid && [booking.uuid]
|
||||||
const bookedDays = await getBookedDays(uuid)
|
const bookedDays = await BookingModel.findBookedDays(uuid)
|
||||||
|
|
||||||
const doubleBookedDays = days.filter((day: string): boolean =>
|
const doubleBookedDays = days.filter((day: string): boolean =>
|
||||||
bookedDays.includes(day)
|
bookedDays.includes(day)
|
||||||
@@ -155,8 +154,10 @@ BookingSchema.static(
|
|||||||
}
|
}
|
||||||
)
|
)
|
||||||
|
|
||||||
export default (mongoose.models.Booking ||
|
const BookingModel = (mongoose.models.Booking ||
|
||||||
mongoose.model<BookingDocument, BookingModel>(
|
mongoose.model<BookingDocument, BookingModel>(
|
||||||
'Booking',
|
'Booking',
|
||||||
BookingSchema
|
BookingSchema
|
||||||
)) as BookingModel
|
)) as BookingModel
|
||||||
|
|
||||||
|
export default BookingModel;
|
||||||
|
|||||||
@@ -1,7 +1,9 @@
|
|||||||
import * as mongoose from 'mongoose'
|
import * as mongoose from 'mongoose'
|
||||||
import BookingModel, { Booking, BookingDocument } from './booking'
|
import BookingModel, { Booking, BookingDocument } from './booking'
|
||||||
import BillModel, { Bill } from './bill'
|
import BillModel, { Bill } from './bill'
|
||||||
|
import { getBookedDays as calendarGetBookedDays } from '../lib/googlecalendar'
|
||||||
import { BOOKING_STATUS } from './enums'
|
import { BOOKING_STATUS } from './enums'
|
||||||
|
import { uniqueFilter } from '../helpers/array'
|
||||||
|
|
||||||
let connectedPromise: Promise<mongoose.Mongoose>
|
let connectedPromise: Promise<mongoose.Mongoose>
|
||||||
|
|
||||||
@@ -21,7 +23,12 @@ export async function getBookedDays(
|
|||||||
uuidsToIngore?: string[]
|
uuidsToIngore?: string[]
|
||||||
): Promise<string[]> {
|
): Promise<string[]> {
|
||||||
await connect()
|
await connect()
|
||||||
return BookingModel.findBookedDays(uuidsToIngore)
|
const bookedInDatabase = await BookingModel.findBookedDays(uuidsToIngore);
|
||||||
|
const bookedInCalendar = await calendarGetBookedDays();
|
||||||
|
|
||||||
|
return [ ...bookedInDatabase, ...bookedInCalendar]
|
||||||
|
.filter(uniqueFilter)
|
||||||
|
.sort();
|
||||||
}
|
}
|
||||||
|
|
||||||
export async function getBookingByUUID(uuid: string): Promise<BookingDocument> {
|
export async function getBookingByUUID(uuid: string): Promise<BookingDocument> {
|
||||||
|
|||||||
@@ -16,3 +16,7 @@ export function getNextBigger<T>(array: T[], pivot: T): T {
|
|||||||
|
|
||||||
return array.sort().find((day) => day > pivot)
|
return array.sort().find((day) => day > pivot)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
export function uniqueFilter(value, index, self) {
|
||||||
|
return self.indexOf(value) === index;
|
||||||
|
}
|
||||||
|
|||||||
@@ -1,4 +1,4 @@
|
|||||||
import { parse, format, addDays } from 'date-fns'
|
import { parse, format, addDays, subDays } from 'date-fns'
|
||||||
import { utcToZonedTime } from 'date-fns-tz'
|
import { utcToZonedTime } from 'date-fns-tz'
|
||||||
|
|
||||||
const FRONTEND_FORMAT = 'dd.MM.yyyy'
|
const FRONTEND_FORMAT = 'dd.MM.yyyy'
|
||||||
@@ -21,9 +21,11 @@ export function daysFormatFrontend(days: string[]): string {
|
|||||||
export function getDays({
|
export function getDays({
|
||||||
startDate,
|
startDate,
|
||||||
endDate,
|
endDate,
|
||||||
|
endDateExclusive = false,
|
||||||
}: {
|
}: {
|
||||||
startDate: Date
|
startDate: Date
|
||||||
endDate: Date
|
endDate: Date
|
||||||
|
endDateExclusive?: boolean
|
||||||
}): string[] {
|
}): string[] {
|
||||||
let currentDay = new Date(startDate.getTime())
|
let currentDay = new Date(startDate.getTime())
|
||||||
const days = [dateFormatBackend(currentDay)]
|
const days = [dateFormatBackend(currentDay)]
|
||||||
@@ -32,7 +34,9 @@ export function getDays({
|
|||||||
return days
|
return days
|
||||||
}
|
}
|
||||||
|
|
||||||
while (currentDay < endDate) {
|
const inclusiveEndDate = endDateExclusive ? subDays(endDate, 1) : endDate;
|
||||||
|
|
||||||
|
while (currentDay < inclusiveEndDate) {
|
||||||
currentDay = addDays(currentDay, 1)
|
currentDay = addDays(currentDay, 1)
|
||||||
days.push(dateFormatBackend(currentDay))
|
days.push(dateFormatBackend(currentDay))
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,5 +1,7 @@
|
|||||||
import { google } from 'googleapis'
|
import { google } from 'googleapis'
|
||||||
|
import { getBaseURL } from '../helpers/url';
|
||||||
import { Booking } from '../db/booking'
|
import { Booking } from '../db/booking'
|
||||||
|
import { getDays } from '../helpers/date';
|
||||||
|
|
||||||
const calendarId = process.env.GOOGLE_CALENDAR_ID
|
const calendarId = process.env.GOOGLE_CALENDAR_ID
|
||||||
let credentials: object
|
let credentials: object
|
||||||
@@ -23,13 +25,21 @@ const calendar = google.calendar({
|
|||||||
auth,
|
auth,
|
||||||
})
|
})
|
||||||
|
|
||||||
export async function getNewEvents() {
|
export async function getBookedDays() {
|
||||||
const { data } = await calendar.events.list({
|
const { data } = await calendar.events.list({
|
||||||
calendarId,
|
calendarId,
|
||||||
timeMin: new Date().toISOString(),
|
timeMin: new Date().toISOString(),
|
||||||
|
timeZone: 'utc',
|
||||||
})
|
})
|
||||||
|
|
||||||
return data.items
|
return data.items
|
||||||
|
// ignore non all-day events
|
||||||
|
.filter(event => !!event.start.date)
|
||||||
|
.flatMap(event => getDays({
|
||||||
|
startDate: new Date(event.start.date),
|
||||||
|
endDate: new Date(event.end.date),
|
||||||
|
endDateExclusive: true
|
||||||
|
}))
|
||||||
}
|
}
|
||||||
|
|
||||||
function getSummary(booking: Partial<Booking>): string {
|
function getSummary(booking: Partial<Booking>): string {
|
||||||
@@ -44,12 +54,18 @@ function getSummary(booking: Partial<Booking>): string {
|
|||||||
return summary
|
return summary
|
||||||
}
|
}
|
||||||
|
|
||||||
|
function getDescription(booking: Booking): string {
|
||||||
|
const bookingUrl = `${getBaseURL()}/admin/booking/${booking.uuid}`;
|
||||||
|
|
||||||
|
return `Managelink ${bookingUrl}`;
|
||||||
|
}
|
||||||
|
|
||||||
export async function createCalendarEvent(booking: Booking): Promise<Booking> {
|
export async function createCalendarEvent(booking: Booking): Promise<Booking> {
|
||||||
const response = await calendar.events.insert({
|
const response = await calendar.events.insert({
|
||||||
calendarId,
|
calendarId,
|
||||||
requestBody: {
|
requestBody: {
|
||||||
summary: getSummary(booking),
|
summary: getSummary(booking),
|
||||||
// TODO: description,
|
description: getDescription(booking),
|
||||||
start: { date: booking.startDate },
|
start: { date: booking.startDate },
|
||||||
end: { date: booking.endDate },
|
end: { date: booking.endDate },
|
||||||
},
|
},
|
||||||
@@ -64,7 +80,9 @@ export async function deleteCalendarEvent(booking: Booking) {
|
|||||||
await calendar.events.delete({
|
await calendar.events.delete({
|
||||||
calendarId,
|
calendarId,
|
||||||
eventId: booking.calendarEventId,
|
eventId: booking.calendarEventId,
|
||||||
})
|
// TODO: really useful?
|
||||||
|
sendNotifications: true,
|
||||||
|
});
|
||||||
|
|
||||||
booking.calendarEventId = null
|
booking.calendarEventId = null
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user