implemented calendar endpoint; supplied external tests pass

main
Inga 🏳‍🌈 5 days ago
parent 7af426c262
commit 3ecf3404df
  1. 1
      service/src/app/app.controller.spec.ts
  2. 12
      service/src/calendar/calendar.controller.spec.ts
  3. 12
      service/src/calendar/calendar.service.spec.ts
  4. 15
      service/src/calendar/calendar.service.ts
  5. 64
      service/src/db/index.ts
  6. 15
      service/src/types/enums.ts

@ -14,6 +14,7 @@ describe('AppController', () => {
provide: 'dbClient', provide: 'dbClient',
useValue: { useValue: {
getNumberOfAllSlots: () => Promise.resolve(123), getNumberOfAllSlots: () => Promise.resolve(123),
getAvailableSlots: () => Promise.resolve([]),
} satisfies DbClient, } satisfies DbClient,
}, },
AppService, AppService,

@ -1,6 +1,7 @@
import { Test, TestingModule } from '@nestjs/testing'; import { Test, TestingModule } from '@nestjs/testing';
import { CalendarController } from './calendar.controller'; import { CalendarController } from './calendar.controller';
import { CalendarService } from './calendar.service'; import { CalendarService } from './calendar.service';
import { DbClient } from 'src/db';
describe('CalendarController', () => { describe('CalendarController', () => {
let controller: CalendarController; let controller: CalendarController;
@ -8,7 +9,16 @@ describe('CalendarController', () => {
beforeEach(async () => { beforeEach(async () => {
const module: TestingModule = await Test.createTestingModule({ const module: TestingModule = await Test.createTestingModule({
controllers: [CalendarController], controllers: [CalendarController],
providers: [CalendarService], providers: [
{
provide: 'dbClient',
useValue: {
getNumberOfAllSlots: () => Promise.resolve(123),
getAvailableSlots: () => Promise.resolve([]),
} satisfies DbClient,
},
CalendarService,
],
}).compile(); }).compile();
controller = module.get<CalendarController>(CalendarController); controller = module.get<CalendarController>(CalendarController);

@ -1,12 +1,22 @@
import { Test, TestingModule } from '@nestjs/testing'; import { Test, TestingModule } from '@nestjs/testing';
import { CalendarService } from './calendar.service'; import { CalendarService } from './calendar.service';
import { DbClient } from 'src/db';
describe('CalendarService', () => { describe('CalendarService', () => {
let service: CalendarService; let service: CalendarService;
beforeEach(async () => { beforeEach(async () => {
const module: TestingModule = await Test.createTestingModule({ const module: TestingModule = await Test.createTestingModule({
providers: [CalendarService], providers: [
{
provide: 'dbClient',
useValue: {
getNumberOfAllSlots: () => Promise.resolve(123),
getAvailableSlots: () => Promise.resolve([]),
} satisfies DbClient,
},
CalendarService,
],
}).compile(); }).compile();
service = module.get<CalendarService>(CalendarService); service = module.get<CalendarService>(CalendarService);

@ -1,10 +1,19 @@
import { Injectable } from '@nestjs/common'; import { Inject, Injectable } from '@nestjs/common';
import { QueryParamsDto, QueryResponseDto } from './calendar.dto'; import { QueryParamsDto, QueryResponseDto } from './calendar.dto';
import { DbClient } from 'src/db';
@Injectable() @Injectable()
export class CalendarService { export class CalendarService {
constructor(
@Inject('dbClient')
private readonly dbClient: DbClient,
) {}
async getAvailableSlots(queryParamsDto: QueryParamsDto) { async getAvailableSlots(queryParamsDto: QueryParamsDto) {
console.log(queryParamsDto); const rows = await this.dbClient.getAvailableSlots(queryParamsDto);
return Promise.resolve([new QueryResponseDto(1, new Date())]); return rows.map(
(row) =>
new QueryResponseDto(parseInt(row.count, 10), new Date(row.start_date)),
);
} }
} }

@ -1,7 +1,17 @@
import { OnModuleDestroy } from '@nestjs/common'; import { OnModuleDestroy } from '@nestjs/common';
import { Pool } from 'pg'; import { Pool } from 'pg';
interface QueryParams {
language: string;
products: string[];
rating: string;
date: string;
}
type QueryResponseRow = Record<'start_date' | 'count', string>;
export interface DbClient { export interface DbClient {
getAvailableSlots(params: QueryParams): Promise<QueryResponseRow[]>;
getNumberOfAllSlots(): Promise<number>; getNumberOfAllSlots(): Promise<number>;
} }
@ -25,6 +35,60 @@ export const createDbClient = async (
return parseInt(result.rows[0]?.count ?? '0'); return parseInt(result.rows[0]?.count ?? '0');
}, },
getAvailableSlots: async ({ language, products, rating, date }) => {
const result = await pool.query<QueryResponseRow>({
text: `
select
available_slots.start_date start_date,
count(*) count
from
slots available_slots
join
sales_managers managers on managers.id = available_slots.sales_manager_id
where
$1 = ANY(managers.languages)
and
managers.products @> $2
and
$3 = ANY(managers.customer_ratings)
and
available_slots.booked = false
and
available_slots.start_date::timestamp::date = TO_DATE($4, 'YYYY-MM-DD')
and
not exists (
select *
from slots unavailable_slots
where
unavailable_slots.sales_manager_id = available_slots.sales_manager_id
and
booked = true
and
(
(
unavailable_slots.start_date >= available_slots.start_date
and
unavailable_slots.start_date < available_slots.end_date
)
or
(
unavailable_slots.end_date > available_slots.start_date
and
unavailable_slots.end_date <= available_slots.end_date
)
)
)
group by
available_slots.start_date
order by
available_slots.start_date asc
`,
values: [language, products, rating, date],
});
return result.rows;
},
onModuleDestroy: async () => { onModuleDestroy: async () => {
await pool.end(); await pool.end();
}, },

@ -0,0 +1,15 @@
export enum ProductType {
SolarPanels = 'SolarPanels',
Heatpumps = 'Heatpumps',
}
export enum Language {
German = 'German',
English = 'English',
}
export enum CustomerRating {
Gold = 'Gold',
Silver = 'Silver',
Bronze = 'Bronze',
}
Loading…
Cancel
Save