mirror of
https://dev.azure.com/globalhealthx/EMR/_git/helix-engage-server
synced 2026-05-18 20:08:19 +00:00
- QrService: generates QR PNG from appointment data, cached in-memory
- GET /api/messaging/qr/:appointmentId serves the image (Gupshup needs URL)
- sendImage added to MessagingProvider + GupshupProvider
- send_appointment_qr tool registered in ToolRegistry
- Flow JSON updated: QR sent after booking confirmation
- Variable interpolation now supports dot notation ({{result.field}})
- SIDECAR_PUBLIC_URL env var for the QR image URL
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
57 lines
2.3 KiB
TypeScript
57 lines
2.3 KiB
TypeScript
import { Injectable } from '@nestjs/common';
|
|
|
|
@Injectable()
|
|
export class FlowVariableService {
|
|
// Replace {{variableName}} with values from session variables
|
|
interpolate(template: string, variables: Record<string, any>): string {
|
|
return template.replace(/\{\{([\w.]+)\}\}/g, (match, path) => {
|
|
// Support dot notation: {{bookingResult.appointmentId}}
|
|
const parts = path.split('.');
|
|
let value: any = variables;
|
|
for (const part of parts) {
|
|
value = value?.[part];
|
|
if (value === undefined) return match;
|
|
}
|
|
if (value === null) return match;
|
|
if (typeof value === 'object') return JSON.stringify(value);
|
|
return String(value);
|
|
});
|
|
}
|
|
|
|
// Interpolate all string values in an object
|
|
interpolateObject(obj: Record<string, string>, variables: Record<string, any>): Record<string, any> {
|
|
const result: Record<string, any> = {};
|
|
for (const [key, value] of Object.entries(obj)) {
|
|
result[key] = this.interpolate(value, variables);
|
|
}
|
|
return result;
|
|
}
|
|
|
|
// Execute expressions for SetVariableBlock
|
|
evaluateExpression(expression: string, value: string, variables: Record<string, any>): any {
|
|
switch (expression) {
|
|
case 'extract_id': {
|
|
// Extract second segment: "doc:{uuid}:{name}" → uuid, "dept:{name}" → name
|
|
const parts = value.split(':');
|
|
return parts.length >= 2 ? parts[1] : value;
|
|
}
|
|
case 'extract_datetime': {
|
|
// Extract datetime from "slot:{doctorId}:{datetime}" → "2026-04-21T14:00:00"
|
|
const parts = value.split(':');
|
|
// Rejoin from index 2 onwards (datetime contains colons: 2026-04-21T14:00:00)
|
|
return parts.length >= 3 ? parts.slice(2).join(':') : value;
|
|
}
|
|
case 'date_tomorrow': {
|
|
const d = new Date(Date.now() + 86400000);
|
|
return d.toISOString().split('T')[0];
|
|
}
|
|
case 'date_day_after': {
|
|
const d = new Date(Date.now() + 2 * 86400000);
|
|
return d.toISOString().split('T')[0];
|
|
}
|
|
default:
|
|
return this.interpolate(value, variables);
|
|
}
|
|
}
|
|
}
|