177 lines
4.5 KiB
TypeScript
177 lines
4.5 KiB
TypeScript
'use server';
|
|
|
|
import { loadCurrentUserAccount } from '@/app/home/(user)/_lib/server/load-user-account';
|
|
import { MontonioOrderHandlerService } from '@/packages/billing/montonio/src';
|
|
import { addToCart, deleteLineItem, retrieveCart } from '@lib/data/cart';
|
|
import { getCartId } from '@lib/data/cookies';
|
|
import { StoreCartLineItem, StoreProductVariant } from '@medusajs/types';
|
|
import { isSameMinute } from 'date-fns';
|
|
import { z } from 'zod';
|
|
|
|
import {
|
|
cancelReservation,
|
|
getOrderedTtoServices,
|
|
} from '~/lib/services/reservation.service';
|
|
|
|
import { createCartEntriesLog } from './audit/cartEntries';
|
|
import { getAvailableAppointmentsForService } from './connected-online.service';
|
|
|
|
const env = () =>
|
|
z
|
|
.object({
|
|
medusaBackendPublicUrl: z
|
|
.string({
|
|
error: 'MEDUSA_BACKEND_PUBLIC_URL is required',
|
|
})
|
|
.min(1),
|
|
siteUrl: z
|
|
.string({
|
|
error: 'NEXT_PUBLIC_SITE_URL is required',
|
|
})
|
|
.min(1),
|
|
})
|
|
.parse({
|
|
medusaBackendPublicUrl: (process.env.DEV_MONTONIO_CALLBACK_URL || process.env.MEDUSA_BACKEND_PUBLIC_URL)!,
|
|
siteUrl: (process.env.DEV_MONTONIO_CALLBACK_URL || process.env.NEXT_PUBLIC_SITE_URL)!,
|
|
});
|
|
|
|
export async function handleAddToCart({
|
|
selectedVariant,
|
|
countryCode,
|
|
}: {
|
|
selectedVariant: Pick<StoreProductVariant, 'id'>;
|
|
countryCode: string;
|
|
}) {
|
|
try {
|
|
} catch (e) {
|
|
console.error('medusa card error: ', e);
|
|
}
|
|
const { account } = await loadCurrentUserAccount();
|
|
if (!account) {
|
|
throw new Error('Account not found');
|
|
}
|
|
|
|
const quantity = 1;
|
|
const { newCart, addedItem } = await addToCart({
|
|
variantId: selectedVariant.id,
|
|
quantity,
|
|
countryCode,
|
|
});
|
|
|
|
await createCartEntriesLog({
|
|
variantId: selectedVariant.id,
|
|
operation: 'ADD_TO_CART',
|
|
accountId: account.id,
|
|
cartId: newCart.id,
|
|
});
|
|
|
|
return { cart: newCart, addedItem };
|
|
}
|
|
|
|
export async function handleDeleteCartItem({ lineId }: { lineId: string }) {
|
|
await deleteLineItem(lineId);
|
|
await cancelReservation(lineId);
|
|
|
|
const cartId = await getCartId();
|
|
const { account } = await loadCurrentUserAccount();
|
|
if (!account) {
|
|
throw new Error('Account not found');
|
|
}
|
|
|
|
await createCartEntriesLog({
|
|
variantId: lineId,
|
|
operation: 'REMOVE_FROM_CART',
|
|
accountId: account.id,
|
|
cartId: cartId!,
|
|
});
|
|
}
|
|
|
|
export async function handleNavigateToPayment({
|
|
language,
|
|
paymentSessionId,
|
|
amount,
|
|
currencyCode,
|
|
cartId,
|
|
}: {
|
|
language: string;
|
|
paymentSessionId: string;
|
|
amount: number;
|
|
currencyCode: string;
|
|
cartId: string;
|
|
}) {
|
|
const { account } = await loadCurrentUserAccount();
|
|
if (!account) {
|
|
throw new Error('Account not found');
|
|
}
|
|
|
|
const cart = await retrieveCart();
|
|
if (!cart) {
|
|
throw new Error('No cart found');
|
|
}
|
|
const orderedTtoServices = await getOrderedTtoServices({ cart });
|
|
|
|
if (orderedTtoServices?.length) {
|
|
const unavailableLineItemIds: string[] = [];
|
|
for (const ttoService of orderedTtoServices) {
|
|
const availabilities = await getAvailableAppointmentsForService(
|
|
ttoService.service_id,
|
|
ttoService.provider.key,
|
|
ttoService.location_sync_id,
|
|
new Date(ttoService.start_time),
|
|
1,
|
|
);
|
|
const isAvailable = availabilities?.T_Booking?.length
|
|
? availabilities.T_Booking.find((timeSlot) =>
|
|
isSameMinute(ttoService.start_time, timeSlot.StartTime),
|
|
)
|
|
: false;
|
|
|
|
if (!isAvailable) {
|
|
unavailableLineItemIds.push(ttoService.medusa_cart_line_item_id!);
|
|
}
|
|
}
|
|
|
|
if (unavailableLineItemIds.length) {
|
|
return { unavailableLineItemIds };
|
|
}
|
|
}
|
|
|
|
const paymentLink =
|
|
await new MontonioOrderHandlerService().getMontonioPaymentLink({
|
|
notificationUrl: `${env().medusaBackendPublicUrl}/hooks/payment/montonio_montonio`,
|
|
returnUrl: `${env().siteUrl}/home/cart/montonio-callback`,
|
|
amount,
|
|
currency: currencyCode.toUpperCase(),
|
|
description: `Order from Medreport`,
|
|
locale: language,
|
|
merchantReference: `${account.id}:${paymentSessionId}:${cartId}`,
|
|
});
|
|
|
|
await createCartEntriesLog({
|
|
operation: 'NAVIGATE_TO_PAYMENT',
|
|
accountId: account.id,
|
|
cartId: cart.id,
|
|
});
|
|
|
|
return { url: paymentLink };
|
|
}
|
|
|
|
export async function handleLineItemTimeout({
|
|
lineItem,
|
|
}: {
|
|
lineItem: StoreCartLineItem;
|
|
}) {
|
|
const { account } = await loadCurrentUserAccount();
|
|
if (!account) {
|
|
throw new Error('Account not found');
|
|
}
|
|
|
|
await deleteLineItem(lineItem.id);
|
|
|
|
await createCartEntriesLog({
|
|
operation: 'LINE_ITEM_TIMEOUT',
|
|
accountId: account.id,
|
|
cartId: lineItem.cart_id,
|
|
});
|
|
}
|