feat: create email template for TTO reservation confirmation
feat: implement order notifications service with TTO reservation confirmation handling feat: create migration for TTO booking email webhook trigger
This commit is contained in:
@@ -1,9 +1,12 @@
|
||||
import { sdk } from '@lib/config';
|
||||
|
||||
import {
|
||||
renderAllResultsReceivedEmail,
|
||||
renderFirstResultsReceivedEmail,
|
||||
renderOrderProcessingEmail,
|
||||
renderPatientFirstResultsReceivedEmail,
|
||||
renderPatientFullResultsReceivedEmail,
|
||||
renderTtoReservationConfirmationEmail,
|
||||
} from '@kit/email-templates';
|
||||
import { getLogger } from '@kit/shared/logger';
|
||||
import { getFullName } from '@kit/shared/utils';
|
||||
@@ -25,13 +28,15 @@ import {
|
||||
} from '~/lib/services/mailer.service';
|
||||
|
||||
type AnalysisOrder = Database['medreport']['Tables']['analysis_orders']['Row'];
|
||||
type TtoReservation =
|
||||
Database['medreport']['Tables']['connected_online_reservation']['Row'];
|
||||
|
||||
export function createAnalysisOrderWebhooksService() {
|
||||
return new AnalysisOrderWebhooksService();
|
||||
export function createOrderWebhooksService() {
|
||||
return new OrderWebhooksService();
|
||||
}
|
||||
|
||||
class AnalysisOrderWebhooksService {
|
||||
private readonly namespace = 'analysis_orders.webhooks';
|
||||
class OrderWebhooksService {
|
||||
private readonly namespace = 'orders.webhooks';
|
||||
|
||||
async handleStatusChangeWebhook(analysisOrder: AnalysisOrder) {
|
||||
const logger = await getLogger();
|
||||
@@ -90,6 +95,128 @@ class AnalysisOrderWebhooksService {
|
||||
}
|
||||
}
|
||||
|
||||
async handleTtoReservationConfirmationWebhook(
|
||||
ttoReservation: TtoReservation,
|
||||
) {
|
||||
const logger = await getLogger();
|
||||
const ctx = {
|
||||
ttoReservationId: ttoReservation.id,
|
||||
namespace: this.namespace,
|
||||
};
|
||||
|
||||
try {
|
||||
const userContact = await getUserContactAdmin(ttoReservation.user_id);
|
||||
if (!userContact.email) {
|
||||
await createNotificationLog({
|
||||
action: NotificationAction.TTO_ORDER_CONFIRMATION,
|
||||
status: 'FAIL',
|
||||
comment: 'No email found for ' + ttoReservation.user_id,
|
||||
relatedRecordId: ttoReservation.id,
|
||||
});
|
||||
logger.warn(ctx, 'No email found ');
|
||||
return;
|
||||
}
|
||||
const supabaseClient = getSupabaseServerAdminClient();
|
||||
if (!ttoReservation.medusa_cart_line_item_id) {
|
||||
await createNotificationLog({
|
||||
action: NotificationAction.TTO_ORDER_CONFIRMATION,
|
||||
status: 'FAIL',
|
||||
comment: 'No cart item id found for ' + ttoReservation.user_id,
|
||||
relatedRecordId: ttoReservation.id,
|
||||
});
|
||||
logger.warn(ctx, 'No cart item id found ');
|
||||
return;
|
||||
}
|
||||
const [
|
||||
{ data: cartItem },
|
||||
{ data: location },
|
||||
{ data: serviceProvider },
|
||||
] = await Promise.all([
|
||||
supabaseClient
|
||||
.from('cart_line_item')
|
||||
.select('cart_id,title')
|
||||
.eq('id', ttoReservation.medusa_cart_line_item_id)
|
||||
.single(),
|
||||
supabaseClient
|
||||
.schema('medreport')
|
||||
.from('connected_online_locations')
|
||||
.select('name,address')
|
||||
.eq('sync_id', ttoReservation.location_sync_id || 0)
|
||||
.single(),
|
||||
supabaseClient
|
||||
.schema('medreport')
|
||||
.from('connected_online_providers')
|
||||
.select('email,phone_number,name')
|
||||
.eq('id', ttoReservation.clinic_id)
|
||||
.single(),
|
||||
]);
|
||||
|
||||
if (!cartItem) {
|
||||
await createNotificationLog({
|
||||
action: NotificationAction.TTO_ORDER_CONFIRMATION,
|
||||
status: 'FAIL',
|
||||
comment: 'No medusa cart item found for ' + ttoReservation.user_id,
|
||||
relatedRecordId: ttoReservation.medusa_cart_line_item_id,
|
||||
});
|
||||
logger.warn(ctx, 'No cart item found ');
|
||||
return;
|
||||
}
|
||||
|
||||
const [{ data: orderCart }] = await Promise.all([
|
||||
supabaseClient
|
||||
.from('order_cart')
|
||||
.select('order_id')
|
||||
.eq('cart_id', cartItem.cart_id)
|
||||
.single(),
|
||||
]);
|
||||
|
||||
if (!orderCart) {
|
||||
await createNotificationLog({
|
||||
action: NotificationAction.TTO_ORDER_CONFIRMATION,
|
||||
status: 'FAIL',
|
||||
comment: 'No medusa order cart found for ' + ttoReservation.user_id,
|
||||
relatedRecordId: cartItem.cart_id,
|
||||
});
|
||||
logger.warn(ctx, 'No order cart found ');
|
||||
return;
|
||||
}
|
||||
|
||||
await sendEmailFromTemplate(
|
||||
renderTtoReservationConfirmationEmail,
|
||||
{
|
||||
language: userContact.preferred_locale ?? 'et',
|
||||
recipientName: getFullName(userContact.name, userContact.last_name),
|
||||
startTime: ttoReservation.start_time,
|
||||
orderName: cartItem.title,
|
||||
locationName: location?.name,
|
||||
locationAddress: location?.address,
|
||||
orderId: orderCart.order_id,
|
||||
serviceProviderName: serviceProvider?.name,
|
||||
serviceProviderEmail: serviceProvider?.email,
|
||||
serviceProviderPhone: serviceProvider?.phone_number,
|
||||
},
|
||||
userContact.email,
|
||||
);
|
||||
|
||||
return createNotificationLog({
|
||||
action: NotificationAction.TTO_ORDER_CONFIRMATION,
|
||||
status: 'SUCCESS',
|
||||
relatedRecordId: orderCart.order_id,
|
||||
});
|
||||
} catch (e: any) {
|
||||
createNotificationLog({
|
||||
action: NotificationAction.TTO_ORDER_CONFIRMATION,
|
||||
status: 'FAIL',
|
||||
comment: e?.message,
|
||||
relatedRecordId: ttoReservation.id,
|
||||
});
|
||||
logger.error(
|
||||
ctx,
|
||||
`Error while processing tto reservation: ${JSON.stringify(e)}`,
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
async sendProcessingNotification(analysisOrder: AnalysisOrder) {
|
||||
const logger = await getLogger();
|
||||
const supabase = getSupabaseServerAdminClient();
|
||||
Reference in New Issue
Block a user