You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
78 lines
2.3 KiB
78 lines
2.3 KiB
import { Injectable, Logger } from '@nestjs/common'; |
|
import { ConfigService } from '@nestjs/config'; |
|
|
|
export interface PolimedPatient { |
|
id: string; |
|
fullName: string; |
|
birthDate: string; |
|
phone: string; |
|
cardNumber: string; |
|
} |
|
|
|
export interface PolimedAppointment { |
|
id: string; |
|
patientId: string; |
|
patientFullName: string; |
|
doctorFullName: string; |
|
specialty: string; |
|
scheduledFor: string; |
|
status: 'scheduled' | 'completed' | 'cancelled' | 'no_show'; |
|
} |
|
|
|
export type PolimedVisitEventType = |
|
| 'arrived' |
|
| 'service_started' |
|
| 'service_ended' |
|
| 'left_without_service'; |
|
|
|
@Injectable() |
|
export class PolimedClient { |
|
private readonly logger = new Logger(PolimedClient.name); |
|
private readonly baseUrl: string; |
|
|
|
constructor(config: ConfigService) { |
|
this.baseUrl = config.getOrThrow<string>('POLIMED_BASE_URL'); |
|
} |
|
|
|
async searchPatients(query: string, limit = 20): Promise<PolimedPatient[]> { |
|
const url = new URL('/patients/search', this.baseUrl); |
|
url.searchParams.set('q', query); |
|
url.searchParams.set('limit', String(limit)); |
|
return this.fetchJson(url); |
|
} |
|
|
|
async getAppointments(date?: string): Promise<PolimedAppointment[]> { |
|
const url = new URL('/appointments', this.baseUrl); |
|
if (date) url.searchParams.set('date', date); |
|
return this.fetchJson(url); |
|
} |
|
|
|
async getAppointment(id: string): Promise<PolimedAppointment> { |
|
const url = new URL(`/appointments/${id}`, this.baseUrl); |
|
return this.fetchJson(url); |
|
} |
|
|
|
async pushVisitEvent( |
|
appointmentId: string, |
|
event: { type: PolimedVisitEventType; occurredAt: string; source?: string }, |
|
): Promise<void> { |
|
const url = new URL(`/visits/${appointmentId}/events`, this.baseUrl); |
|
const res = await fetch(url, { |
|
method: 'POST', |
|
headers: { 'Content-Type': 'application/json' }, |
|
body: JSON.stringify({ ...event, source: event.source ?? 'reception-video' }), |
|
}); |
|
if (!res.ok) { |
|
this.logger.warn(`pushVisitEvent failed: ${res.status} ${url}`); |
|
throw new Error(`Polimed event failed: ${res.status}`); |
|
} |
|
} |
|
|
|
private async fetchJson<T>(url: URL): Promise<T> { |
|
const res = await fetch(url); |
|
if (!res.ok) { |
|
throw new Error(`Polimed ${url.pathname} failed: ${res.status}`); |
|
} |
|
return (await res.json()) as T; |
|
} |
|
}
|
|
|