Adding ability to monitor court reservations when performing a reservation
This commit is contained in:
parent
8410241219
commit
7bc30f99d0
7 changed files with 142 additions and 4 deletions
15
database/migrations/1709910503052-AddMonitors.ts
Normal file
15
database/migrations/1709910503052-AddMonitors.ts
Normal file
|
|
@ -0,0 +1,15 @@
|
||||||
|
import { MigrationInterface, QueryRunner } from 'typeorm'
|
||||||
|
|
||||||
|
export class AddMonitors1709910503052 implements MigrationInterface {
|
||||||
|
name = 'AddMonitors1709910503052'
|
||||||
|
|
||||||
|
public async up(queryRunner: QueryRunner): Promise<void> {
|
||||||
|
await queryRunner.query(
|
||||||
|
`CREATE TABLE "monitors" ("id" varchar PRIMARY KEY NOT NULL, "type" varchar(32) NOT NULL, "createdAt" datetime NOT NULL, "data" blob NOT NULL)`,
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
public async down(queryRunner: QueryRunner): Promise<void> {
|
||||||
|
await queryRunner.query(`DROP TABLE "monitors"`)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
@ -10,6 +10,7 @@ import { LoggerMiddleware } from './logger/middleware'
|
||||||
import { LoggerModule } from './logger/module'
|
import { LoggerModule } from './logger/module'
|
||||||
import { DatabaseLoggerService } from './logger/service.database_logger'
|
import { DatabaseLoggerService } from './logger/service.database_logger'
|
||||||
import { MembersModule } from './members/module'
|
import { MembersModule } from './members/module'
|
||||||
|
import { MonitoringModule } from './monitoring/module'
|
||||||
import { NtfyModule } from './ntfy/module'
|
import { NtfyModule } from './ntfy/module'
|
||||||
import { RecurringReservationsModule } from './recurringReservations/module'
|
import { RecurringReservationsModule } from './recurringReservations/module'
|
||||||
import { ReservationsModule } from './reservations/module'
|
import { ReservationsModule } from './reservations/module'
|
||||||
|
|
@ -59,6 +60,7 @@ import { WaitingListModule } from './waitingList/module'
|
||||||
MembersModule,
|
MembersModule,
|
||||||
WaitingListModule,
|
WaitingListModule,
|
||||||
NtfyModule,
|
NtfyModule,
|
||||||
|
MonitoringModule,
|
||||||
],
|
],
|
||||||
})
|
})
|
||||||
export class AppModule implements NestModule {
|
export class AppModule implements NestModule {
|
||||||
|
|
|
||||||
52
src/monitoring/entity.ts
Normal file
52
src/monitoring/entity.ts
Normal file
|
|
@ -0,0 +1,52 @@
|
||||||
|
import { Transform, Type } from 'class-transformer'
|
||||||
|
import { TransformationType } from 'class-transformer'
|
||||||
|
import { Dayjs } from 'dayjs'
|
||||||
|
import { Column, Entity, PrimaryGeneratedColumn } from 'typeorm'
|
||||||
|
|
||||||
|
import dayjs from '../common/dayjs'
|
||||||
|
|
||||||
|
export enum MonitorType {
|
||||||
|
CourtReservations = 'court_reservations',
|
||||||
|
}
|
||||||
|
|
||||||
|
@Entity({ name: 'monitors' })
|
||||||
|
export class Monitor {
|
||||||
|
@PrimaryGeneratedColumn('uuid')
|
||||||
|
id: string
|
||||||
|
|
||||||
|
@Column('varchar', { length: 32, nullable: false })
|
||||||
|
type: MonitorType
|
||||||
|
|
||||||
|
@Column('datetime', {
|
||||||
|
nullable: false,
|
||||||
|
transformer: {
|
||||||
|
to: (value: Dayjs) => value.format(),
|
||||||
|
from: (value: Date) => dayjs(value),
|
||||||
|
},
|
||||||
|
})
|
||||||
|
@Type(() => Dayjs)
|
||||||
|
@Transform(({ value, type }) => {
|
||||||
|
switch (type) {
|
||||||
|
case TransformationType.PLAIN_TO_CLASS:
|
||||||
|
return dayjs(value)
|
||||||
|
case TransformationType.CLASS_TO_PLAIN:
|
||||||
|
return value.format()
|
||||||
|
default:
|
||||||
|
return value
|
||||||
|
}
|
||||||
|
})
|
||||||
|
createdAt: Dayjs
|
||||||
|
|
||||||
|
@Column('blob', {
|
||||||
|
nullable: false,
|
||||||
|
transformer: {
|
||||||
|
to: (value) => value,
|
||||||
|
from: (value) => value,
|
||||||
|
},
|
||||||
|
})
|
||||||
|
data: unknown
|
||||||
|
|
||||||
|
constructor(partial: Partial<Monitor>) {
|
||||||
|
Object.assign(this, partial)
|
||||||
|
}
|
||||||
|
}
|
||||||
14
src/monitoring/module.ts
Normal file
14
src/monitoring/module.ts
Normal file
|
|
@ -0,0 +1,14 @@
|
||||||
|
import { Module } from '@nestjs/common'
|
||||||
|
import { TypeOrmModule } from '@nestjs/typeorm'
|
||||||
|
|
||||||
|
import { LoggerModule } from '../logger/module'
|
||||||
|
import { NtfyModule } from '../ntfy/module'
|
||||||
|
import { Monitor } from './entity'
|
||||||
|
import { MonitorsService } from './service'
|
||||||
|
|
||||||
|
@Module({
|
||||||
|
imports: [LoggerModule, NtfyModule, TypeOrmModule.forFeature([Monitor])],
|
||||||
|
providers: [MonitorsService],
|
||||||
|
exports: [MonitorsService],
|
||||||
|
})
|
||||||
|
export class MonitoringModule {}
|
||||||
19
src/monitoring/service.ts
Normal file
19
src/monitoring/service.ts
Normal file
|
|
@ -0,0 +1,19 @@
|
||||||
|
import { Injectable } from '@nestjs/common'
|
||||||
|
import { InjectRepository } from '@nestjs/typeorm'
|
||||||
|
import { Repository } from 'typeorm'
|
||||||
|
|
||||||
|
import { Monitor, MonitorType } from './entity'
|
||||||
|
|
||||||
|
@Injectable()
|
||||||
|
export class MonitorsService {
|
||||||
|
constructor(
|
||||||
|
@InjectRepository(Monitor)
|
||||||
|
private readonly monitorsRepository: Repository<Monitor>,
|
||||||
|
) {}
|
||||||
|
|
||||||
|
async performMonitor(type: MonitorType, data: unknown) {
|
||||||
|
await this.monitorsRepository.save(
|
||||||
|
this.monitorsRepository.create({ type, data }),
|
||||||
|
)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
@ -509,6 +509,7 @@ export class BaanReserverenService {
|
||||||
try {
|
try {
|
||||||
await this.init()
|
await this.init()
|
||||||
await this.navigateToDay(reservation.dateRangeStart)
|
await this.navigateToDay(reservation.dateRangeStart)
|
||||||
|
await this.monitorCourtReservations()
|
||||||
await this.selectAvailableTime(reservation)
|
await this.selectAvailableTime(reservation)
|
||||||
await this.selectOwner(reservation.ownerId)
|
await this.selectOwner(reservation.ownerId)
|
||||||
await this.selectOpponent(
|
await this.selectOpponent(
|
||||||
|
|
@ -591,10 +592,19 @@ export class BaanReserverenService {
|
||||||
return courtStatuses
|
return courtStatuses
|
||||||
}
|
}
|
||||||
|
|
||||||
public async monitorCourtReservations(date: Dayjs) {
|
public async monitorCourtReservations(date?: Dayjs, swallowError = true) {
|
||||||
await this.init()
|
try {
|
||||||
await this.navigateToDay(date)
|
if (date) {
|
||||||
return await this.getAllCourtStatuses()
|
await this.init()
|
||||||
|
await this.navigateToDay(date)
|
||||||
|
}
|
||||||
|
return await this.getAllCourtStatuses()
|
||||||
|
} catch (error: unknown) {
|
||||||
|
this.loggerService.error('Failed to monitor court reservations')
|
||||||
|
if (!swallowError) {
|
||||||
|
throw error
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
26
test/app.e2e.spec.ts
Normal file
26
test/app.e2e.spec.ts
Normal file
|
|
@ -0,0 +1,26 @@
|
||||||
|
import { INestApplication } from '@nestjs/common'
|
||||||
|
import { Test, TestingModule } from '@nestjs/testing'
|
||||||
|
import * as request from 'supertest'
|
||||||
|
|
||||||
|
import { AppModule } from '../src/app.module'
|
||||||
|
|
||||||
|
describe('AppController (e2e)', () => {
|
||||||
|
let app: INestApplication
|
||||||
|
|
||||||
|
beforeEach(async () => {
|
||||||
|
const moduleFixture: TestingModule = await Test.createTestingModule({
|
||||||
|
imports: [AppModule],
|
||||||
|
}).compile()
|
||||||
|
|
||||||
|
app = moduleFixture.createNestApplication()
|
||||||
|
await app.init()
|
||||||
|
})
|
||||||
|
|
||||||
|
afterAll(async () => {
|
||||||
|
await app.close()
|
||||||
|
})
|
||||||
|
|
||||||
|
it('/ (GET)', async () => {
|
||||||
|
await request(app.getHttpServer()).get('/').expect(404)
|
||||||
|
})
|
||||||
|
})
|
||||||
Loading…
Add table
Reference in a new issue