translations, remove random empty lines, refactor

This commit is contained in:
Helena
2025-09-19 17:28:45 +03:00
parent c50b75ce9b
commit 961f726520
11 changed files with 166 additions and 115 deletions

View File

@@ -0,0 +1,40 @@
import { getSupabaseServerClient } from '@kit/supabase/server-client';
export const createCartEntriesLog = async ({
operation,
accountId,
cartId,
variantId,
comment,
}: {
operation: string;
accountId: string;
cartId: string;
variantId?: string;
comment?: string;
}) => {
try {
const supabase = getSupabaseServerClient();
const {
data: { user },
error: userError,
} = await supabase.auth.getUser();
if (userError || !user) {
console.error('No authenticated user found; skipping audit insert');
return;
}
return supabase.schema('audit').from('cart_entries').insert({
operation,
account_id: accountId,
cart_id: cartId,
changed_by: user.id,
variant_id: variantId,
comment,
});
} catch (error) {
console.error('Failed to insert doctor page view log', error);
}
};

View File

@@ -5,25 +5,13 @@ import { MontonioOrderHandlerService } from '@/packages/billing/montonio/src';
import { addToCart, deleteLineItem, retrieveCart } from '@lib/data/cart'; import { addToCart, deleteLineItem, retrieveCart } from '@lib/data/cart';
import { getCartId } from '@lib/data/cookies'; import { getCartId } from '@lib/data/cookies';
import { StoreCartLineItem, StoreProductVariant } from '@medusajs/types'; import { StoreCartLineItem, StoreProductVariant } from '@medusajs/types';
import { z } from 'zod';
import { getSupabaseServerClient } from '@kit/supabase/server-client';
import { cancelReservation, getOrderedTtoServices } from '~/lib/services/reservation.service';
import { isSameMinute } from 'date-fns'; import { isSameMinute } from 'date-fns';
import { z } from 'zod';
import { getSupabaseServerClient } from '@kit/supabase/server-client';
import { cancelReservation, getOrderedTtoServices } from '~/lib/services/reservation.service';
import { createCartEntriesLog } from './audit/cartEntries';
import { getAvailableAppointmentsForService } from './connected-online.service'; import { getAvailableAppointmentsForService } from './connected-online.service';
const env = () => const env = () =>
z z
.object({ .object({
@@ -50,8 +38,7 @@ export async function handleAddToCart({
selectedVariant: Pick<StoreProductVariant, 'id'>; selectedVariant: Pick<StoreProductVariant, 'id'>;
countryCode: string; countryCode: string;
}) { }) {
const supabase = getSupabaseServerClient(); const { account } = await loadCurrentUserAccount();
const { account, user } = await loadCurrentUserAccount();
if (!account) { if (!account) {
throw new Error('Account not found'); throw new Error('Account not found');
} }
@@ -63,16 +50,12 @@ export async function handleAddToCart({
countryCode, countryCode,
}); });
const { error } = await supabase.schema('audit').from('cart_entries').insert({ await createCartEntriesLog({
variant_id: selectedVariant.id, variantId: selectedVariant.id,
operation: 'ADD_TO_CART', operation: 'ADD_TO_CART',
account_id: account.id, accountId: account.id,
cart_id: newCart.id, cartId: newCart.id,
changed_by: user.id,
}); });
if (error) {
throw new Error('Error logging cart entry: ' + error.message);
}
return { cart: newCart, addedItem }; return { cart: newCart, addedItem };
} }
@@ -81,23 +64,18 @@ export async function handleDeleteCartItem({ lineId }: { lineId: string }) {
await deleteLineItem(lineId); await deleteLineItem(lineId);
await cancelReservation(lineId); await cancelReservation(lineId);
const supabase = getSupabaseServerClient();
const cartId = await getCartId(); const cartId = await getCartId();
const { account, user } = await loadCurrentUserAccount(); const { account } = await loadCurrentUserAccount();
if (!account) { if (!account) {
throw new Error('Account not found'); throw new Error('Account not found');
} }
const { error } = await supabase.schema('audit').from('cart_entries').insert({ await createCartEntriesLog({
variant_id: lineId, variantId: lineId,
operation: 'REMOVE_FROM_CART', operation: 'REMOVE_FROM_CART',
account_id: account.id, accountId: account.id,
cart_id: cartId!, cartId: cartId!,
changed_by: user.id,
}); });
if (error) {
throw new Error('Error logging cart entry: ' + error.message);
}
} }
export async function handleNavigateToPayment({ export async function handleNavigateToPayment({
@@ -107,8 +85,7 @@ export async function handleNavigateToPayment({
language: string; language: string;
paymentSessionId: string; paymentSessionId: string;
}) { }) {
const supabase = getSupabaseServerClient(); const { account } = await loadCurrentUserAccount();
const { account, user } = await loadCurrentUserAccount();
if (!account) { if (!account) {
throw new Error('Account not found'); throw new Error('Account not found');
} }
@@ -120,7 +97,7 @@ export async function handleNavigateToPayment({
const orderedTtoServices = await getOrderedTtoServices({ cart }); const orderedTtoServices = await getOrderedTtoServices({ cart });
if (orderedTtoServices?.length) { if (orderedTtoServices?.length) {
const unavailableLineItemIds: string[] = [] const unavailableLineItemIds: string[] = [];
for (const ttoService of orderedTtoServices) { for (const ttoService of orderedTtoServices) {
const availabilities = await getAvailableAppointmentsForService( const availabilities = await getAvailableAppointmentsForService(
ttoService.service_id, ttoService.service_id,
@@ -129,19 +106,22 @@ export async function handleNavigateToPayment({
new Date(ttoService.start_time), new Date(ttoService.start_time),
1, 1,
); );
const isAvailable = availabilities?.T_Booking?.length ? availabilities.T_Booking.find((timeSlot) => isSameMinute(ttoService.start_time, timeSlot.StartTime)) : false const isAvailable = availabilities?.T_Booking?.length
? availabilities.T_Booking.find((timeSlot) =>
isSameMinute(ttoService.start_time, timeSlot.StartTime),
)
: false;
if (!isAvailable) { if (!isAvailable) {
unavailableLineItemIds.push(ttoService.medusa_cart_line_item_id!) unavailableLineItemIds.push(ttoService.medusa_cart_line_item_id!);
} }
} }
if (unavailableLineItemIds.length) { if (unavailableLineItemIds.length) {
return { unavailableLineItemIds } return { unavailableLineItemIds };
} }
} }
const paymentLink = const paymentLink =
await new MontonioOrderHandlerService().getMontonioPaymentLink({ await new MontonioOrderHandlerService().getMontonioPaymentLink({
notificationUrl: `${env().medusaBackendPublicUrl}/hooks/payment/montonio_montonio`, notificationUrl: `${env().medusaBackendPublicUrl}/hooks/payment/montonio_montonio`,
@@ -153,17 +133,12 @@ export async function handleNavigateToPayment({
merchantReference: `${account.id}:${paymentSessionId}:${cart.id}`, merchantReference: `${account.id}:${paymentSessionId}:${cart.id}`,
}); });
const { error } = await supabase.schema('audit').from('cart_entries').insert({ await createCartEntriesLog({
operation: 'NAVIGATE_TO_PAYMENT', operation: 'NAVIGATE_TO_PAYMENT',
account_id: account.id, accountId: account.id,
cart_id: cart.id, cartId: cart.id,
changed_by: user.id,
}); });
if (error) {
throw new Error('Error logging cart entry: ' + error.message);
}
return { url: paymentLink }; return { url: paymentLink };
} }
@@ -172,21 +147,16 @@ export async function handleLineItemTimeout({
}: { }: {
lineItem: StoreCartLineItem; lineItem: StoreCartLineItem;
}) { }) {
const supabase = getSupabaseServerClient(); const { account } = await loadCurrentUserAccount();
const { account, user } = await loadCurrentUserAccount();
if (!account) { if (!account) {
throw new Error('Account not found'); throw new Error('Account not found');
} }
await deleteLineItem(lineItem.id); await deleteLineItem(lineItem.id);
const { error } = await supabase.schema('audit').from('cart_entries').insert({ await createCartEntriesLog({
operation: 'LINE_ITEM_TIMEOUT', operation: 'LINE_ITEM_TIMEOUT',
account_id: account.id, accountId: account.id,
cart_id: lineItem.cart_id, cartId: lineItem.cart_id,
changed_by: user.id,
}); });
if (error) {
throw new Error('Error logging cart entry: ' + error.message);
}
} }

View File

@@ -11,6 +11,7 @@ import { getSupabaseServerClient } from '@kit/supabase/server-client';
import { EnrichedCartItem } from '../../app/home/(user)/_components/cart/types'; import { EnrichedCartItem } from '../../app/home/(user)/_components/cart/types';
import { loadCurrentUserAccount } from '../../app/home/(user)/_lib/server/load-user-account'; import { loadCurrentUserAccount } from '../../app/home/(user)/_lib/server/load-user-account';
import { createCartEntriesLog } from './audit/cartEntries';
import { handleDeleteCartItem } from './medusaCart.service'; import { handleDeleteCartItem } from './medusaCart.service';
type Locations = Tables<{ schema: 'medreport' }, 'connected_online_locations'>; type Locations = Tables<{ schema: 'medreport' }, 'connected_online_locations'>;
@@ -305,27 +306,19 @@ export async function updateReservationTime(
.throwOnError(); .throwOnError();
logger.info(`Successfully updated reservation ${reservationData}`); logger.info(`Successfully updated reservation ${reservationData}`);
await supabase await createCartEntriesLog({
.schema('audit')
.from('cart_entries')
.insert({
operation: 'CHANGE_RESERVATION', operation: 'CHANGE_RESERVATION',
account_id: account.id, accountId: account.id,
cart_id: cartId, cartId: cartId,
changed_by: user.id,
comment: `${reservationData}`, comment: `${reservationData}`,
}); });
revalidatePath('/home/cart', 'layout'); revalidatePath('/home/cart', 'layout');
} catch (e) { } catch (e) {
logger.error(`Failed to update reservation ${reservationData}`); logger.error(`Failed to update reservation ${reservationData}`);
await supabase await createCartEntriesLog({
.schema('audit')
.from('cart_entries')
.insert({
operation: 'CHANGE_RESERVATION', operation: 'CHANGE_RESERVATION',
account_id: account.id, accountId: account.id,
cart_id: cartId, cartId: cartId,
changed_by: user.id,
comment: `${e}`, comment: `${e}`,
}); });
throw e; throw e;

View File

@@ -5,10 +5,16 @@
"title": "Analysis packages", "title": "Analysis packages",
"description": "Get to know the personal analysis packages and order" "description": "Get to know the personal analysis packages and order"
}, },
"noCategories": "List of services not found, try again later", "noCategories": "Service list not found, please try again later",
"noResults": "No availabilities found for selected dates", "noResults": "No available times on the selected dates",
"serviceNotFound": "Service not found", "services": "Services",
"locations": "Locations",
"showAll": "Show all",
"showAllLocations": "Show all locations",
"bookTimeSuccess": "Time selected",
"bookTimeError": "Failed to select time",
"bookTimeLoading": "Selecting time...", "bookTimeLoading": "Selecting time...",
"serviceNotFound": "Service not found",
"noProducts": "No products found", "noProducts": "No products found",
"timeSlotUnavailable": "Service availability has changed, please select a new time" "timeSlotUnavailable": "Service availability has changed, please select a new time"
} }

View File

@@ -16,7 +16,9 @@
"goToDashboard": "Continue", "goToDashboard": "Continue",
"error": { "error": {
"title": "Something went wrong", "title": "Something went wrong",
"description": "Please try again later." "description": "Please try again later.",
"BOOKING_FAILED": "Service error, please try again later.",
"TIME_SLOT_UNAVAILABLE": "The selected time is not available."
}, },
"timeLeft": "Time left {{timeLeft}}", "timeLeft": "Time left {{timeLeft}}",
"timeoutTitle": "Reservation expired", "timeoutTitle": "Reservation expired",

View File

@@ -147,5 +147,7 @@
"language": "Language", "language": "Language",
"yes": "Yes", "yes": "Yes",
"no": "No", "no": "No",
"preferNotToAnswer": "Prefer not to answer" "preferNotToAnswer": "Prefer not to answer",
"book": "Book",
"change": "Change"
} }

View File

@@ -9,12 +9,27 @@
"status": "Status" "status": "Status"
}, },
"status": { "status": {
"QUEUED": "Waiting to send to lab", "QUEUED": "Queued",
"PROCESSING": "Waiting for results", "PROCESSING": "Processing",
"PARTIAL_ANALYSIS_RESPONSE": "Partial analysis response", "PARTIAL_ANALYSIS_RESPONSE": "Partial results",
"FULL_ANALYSIS_RESPONSE": "All analysis responses received, waiting for doctor response", "FULL_ANALYSIS_RESPONSE": "All results received",
"COMPLETED": "Completed", "COMPLETED": "Confirmed",
"REJECTED": "Rejected",
"CANCELLED": "Cancelled",
"analysisOrder": {
"QUEUED": "Queued",
"PROCESSING": "Sent to Synlab",
"PARTIAL_ANALYSIS_RESPONSE": "Partial results",
"FULL_ANALYSIS_RESPONSE": "All results received, awaiting doctor's summary",
"COMPLETED": "Confirmed",
"REJECTED": "Rejected",
"CANCELLED": "Cancelled"
},
"ttoService": {
"PENDING": "Started",
"CONFIRMED": "Confirmed",
"REJECTED": "Rejected", "REJECTED": "Rejected",
"CANCELLED": "Cancelled" "CANCELLED": "Cancelled"
} }
}
} }

View File

@@ -6,7 +6,13 @@
"description": "Ознакомьтесь с персональными пакетами анализов и закажите" "description": "Ознакомьтесь с персональными пакетами анализов и закажите"
}, },
"noCategories": "Список услуг не найден, попробуйте позже", "noCategories": "Список услуг не найден, попробуйте позже",
"noResults": "Для выбранных дат доступных вариантов не найдено", "noResults": "На выбранные даты нет свободного времени",
"services": "Услуги",
"locations": "Учреждения",
"showAll": "Показать все",
"showAllLocations": "Показать все учреждения",
"bookTimeSuccess": "Время выбрано",
"bookTimeError": "Не удалось выбрать время",
"bookTimeLoading": "Выбор времени...", "bookTimeLoading": "Выбор времени...",
"serviceNotFound": "Услуга не найдена", "serviceNotFound": "Услуга не найдена",
"noProducts": "Товары не найдены", "noProducts": "Товары не найдены",

View File

@@ -16,7 +16,9 @@
"goToDashboard": "Продолжить", "goToDashboard": "Продолжить",
"error": { "error": {
"title": "Что-то пошло не так", "title": "Что-то пошло не так",
"description": "Пожалуйста, попробуйте позже." "description": "Пожалуйста, попробуйте позже.",
"BOOKING_FAILED": "Ошибка сервиса, попробуйте позже.",
"TIME_SLOT_UNAVAILABLE": "Выбранное время недоступно."
}, },
"timeLeft": "Осталось времени {{timeLeft}}", "timeLeft": "Осталось времени {{timeLeft}}",
"timeoutTitle": "Бронирование истекло", "timeoutTitle": "Бронирование истекло",

View File

@@ -10,11 +10,26 @@
}, },
"status": { "status": {
"QUEUED": "Отправлено", "QUEUED": "Отправлено",
"PROCESSING": "Передано в Synlab", "PROCESSING": "В обработке",
"PARTIAL_ANALYSIS_RESPONSE": "Частичные результаты",
"FULL_ANALYSIS_RESPONSE": "Все результаты получены",
"COMPLETED": "Подтверждено",
"REJECTED": "Отклонено",
"CANCELLED": "Отменено",
"analysisOrder": {
"QUEUED": "Отправлено",
"PROCESSING": "Отправлено в Synlab",
"PARTIAL_ANALYSIS_RESPONSE": "Частичные результаты", "PARTIAL_ANALYSIS_RESPONSE": "Частичные результаты",
"FULL_ANALYSIS_RESPONSE": "Все результаты получены, ожидается заключение врача", "FULL_ANALYSIS_RESPONSE": "Все результаты получены, ожидается заключение врача",
"COMPLETED": "Подтверждено", "COMPLETED": "Подтверждено",
"REJECTED": "Возвращено", "REJECTED": "Отклонено",
"CANCELLED": "Отменено"
},
"ttoService": {
"PENDING": "Начато",
"CONFIRMED": "Подтверждено",
"REJECTED": "Отклонено",
"CANCELLED": "Отменено" "CANCELLED": "Отменено"
} }
}
} }

View File

@@ -16,7 +16,7 @@ create table "medreport"."connected_online_service_providers" (
ALTER TABLE audit.request_entries ALTER TABLE audit.request_entries
DROP COLUMN personal_code; DROP COLUMN personal_code;
ALTER TABLE audit.request_entries ADD COLUMN user_id uuid default auth.uid() references auth.users(id); ALTER TABLE audit.request_entries ADD COLUMN user_id uuid default auth.uid();
create policy "insert_own" create policy "insert_own"
on "audit"."request_entries" on "audit"."request_entries"