B2B-52: add Connected Online syncing, tables and functions (#18)
* B2B-52: add Connected Online syncing, tables and functions * clean up * improve autogenerated types * add use server directive --------- Co-authored-by: Helena <helena@Helenas-MacBook-Pro.local>
This commit is contained in:
48
lib/services/audit.service.ts
Normal file
48
lib/services/audit.service.ts
Normal file
@@ -0,0 +1,48 @@
|
||||
'use server'
|
||||
|
||||
import { createClient } from '@supabase/supabase-js';
|
||||
|
||||
import { RequestStatus } from '@/lib/types/audit';
|
||||
import { ConnectedOnlineMethodName } from '@/lib/types/connected-online';
|
||||
import { ExternalApi } from '@/lib/types/external';
|
||||
import { MedipostAction } from '@/lib/types/medipost';
|
||||
|
||||
export default async function logRequestResult(
|
||||
/* personalCode: string, */ requestApi: keyof typeof ExternalApi,
|
||||
requestApiMethod: `${ConnectedOnlineMethodName}` | `${MedipostAction}`,
|
||||
status: RequestStatus,
|
||||
comment?: string,
|
||||
startTime?: string,
|
||||
serviceId?: number,
|
||||
serviceProviderId?: number,
|
||||
) {
|
||||
const supabaseServiceUser = createClient(
|
||||
process.env.NEXT_PUBLIC_SUPABASE_URL!,
|
||||
process.env.NEXT_PUBLIC_SUPABASE_SERVICE_ROLE_KEY!,
|
||||
{
|
||||
auth: {
|
||||
persistSession: false,
|
||||
autoRefreshToken: false,
|
||||
detectSessionInUrl: false,
|
||||
},
|
||||
},
|
||||
);
|
||||
|
||||
const { error } = await supabaseServiceUser
|
||||
.schema('audit')
|
||||
.from('request_entries')
|
||||
.insert({
|
||||
/* personal_code: personalCode, */
|
||||
request_api: requestApi,
|
||||
request_api_method: requestApiMethod,
|
||||
requested_start_date: startTime,
|
||||
status,
|
||||
service_id: serviceId,
|
||||
service_provider_id: serviceProviderId,
|
||||
comment,
|
||||
});
|
||||
|
||||
if (error) {
|
||||
throw new Error('Failed to insert log entry, error: ' + error.message);
|
||||
}
|
||||
}
|
||||
268
lib/services/connected-online.service.ts
Normal file
268
lib/services/connected-online.service.ts
Normal file
@@ -0,0 +1,268 @@
|
||||
'use server'
|
||||
|
||||
import logRequestResult from '@/lib/services/audit.service';
|
||||
import { RequestStatus } from '@/lib/types/audit';
|
||||
import {
|
||||
AvailableAppointmentsResponse,
|
||||
BookTimeResponse,
|
||||
ConfirmedLoadResponse,
|
||||
ConnectedOnlineMethodName,
|
||||
} from '@/lib/types/connected-online';
|
||||
import { ExternalApi } from '@/lib/types/external';
|
||||
import { Tables } from '@/supabase/database.types';
|
||||
import { createClient } from '@/utils/supabase/server';
|
||||
import axios from 'axios';
|
||||
|
||||
export async function getAvailableAppointmentsForService(
|
||||
serviceId: number,
|
||||
startTime?: Date,
|
||||
) {
|
||||
try {
|
||||
const showTimesFrom = startTime ? { StartTime: startTime } : {};
|
||||
|
||||
const response = await axios.post(
|
||||
`${process.env.CONNECTED_ONLINE_URL!}/${ConnectedOnlineMethodName.GetAvailabilities}`,
|
||||
{
|
||||
headers: {
|
||||
'Content-Type': 'application/json; charset=utf-8',
|
||||
},
|
||||
param: JSON.stringify({
|
||||
ServiceID: serviceId,
|
||||
Key: '7T624nlu',
|
||||
Lang: 'et',
|
||||
...showTimesFrom,
|
||||
}),
|
||||
},
|
||||
);
|
||||
|
||||
const responseData: AvailableAppointmentsResponse = JSON.parse(
|
||||
response.data.d,
|
||||
);
|
||||
|
||||
if (
|
||||
responseData?.ErrorCode !== 0 ||
|
||||
!responseData.Data.T_Service?.length ||
|
||||
!responseData.Data.T_Booking?.length
|
||||
) {
|
||||
let comment = `Response returned error code ${responseData.ErrorCode}, message: ${responseData.ErrorMessage}`;
|
||||
if (responseData?.ErrorCode === 0) {
|
||||
comment = responseData.Data.T_Service?.length
|
||||
? `No service present in appointment availability response, service id: ${serviceId}, start time: ${startTime}`
|
||||
: `No booking times present in appointment availability response, service id: ${serviceId}, start time: ${startTime}`;
|
||||
}
|
||||
|
||||
await logRequestResult(
|
||||
ExternalApi.ConnectedOnline,
|
||||
ConnectedOnlineMethodName.GetAvailabilities,
|
||||
RequestStatus.Fail,
|
||||
comment,
|
||||
);
|
||||
|
||||
return null;
|
||||
}
|
||||
|
||||
await logRequestResult(
|
||||
ExternalApi.ConnectedOnline,
|
||||
ConnectedOnlineMethodName.GetAvailabilities,
|
||||
RequestStatus.Success,
|
||||
JSON.stringify(responseData),
|
||||
);
|
||||
return responseData.Data;
|
||||
} catch (error) {
|
||||
await logRequestResult(
|
||||
ExternalApi.ConnectedOnline,
|
||||
ConnectedOnlineMethodName.GetAvailabilities,
|
||||
RequestStatus.Fail,
|
||||
JSON.stringify(error),
|
||||
);
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
export async function bookAppointment(
|
||||
serviceSyncId: number,
|
||||
clinicId: number,
|
||||
appointmentUserId: number,
|
||||
syncUserID: number,
|
||||
startTime: string,
|
||||
locationId = 0,
|
||||
comments = '',
|
||||
isEarlierTimeRequested = false,
|
||||
earlierTimeRequestComment = '',
|
||||
) {
|
||||
const supabase = await createClient();
|
||||
|
||||
try {
|
||||
const {
|
||||
data: { user },
|
||||
} = await supabase.auth.getUser();
|
||||
|
||||
if (!user?.id) {
|
||||
throw new Error('User not authenticated');
|
||||
}
|
||||
|
||||
const [
|
||||
{ data: dbClinic, error: clinicError },
|
||||
{ data: dbService, error: serviceError },
|
||||
] = await Promise.all([
|
||||
supabase
|
||||
.from('connected_online_providers')
|
||||
.select('*')
|
||||
.eq('id', clinicId)
|
||||
.limit(1),
|
||||
supabase
|
||||
.from('connected_online_services')
|
||||
.select('*')
|
||||
.eq('sync_id', serviceSyncId)
|
||||
.eq('clinic_id', clinicId)
|
||||
.limit(1),
|
||||
]);
|
||||
|
||||
if (!dbClinic?.length || !dbService?.length) {
|
||||
return logRequestResult(
|
||||
ExternalApi.ConnectedOnline,
|
||||
ConnectedOnlineMethodName.BookTime,
|
||||
RequestStatus.Fail,
|
||||
dbClinic?.length
|
||||
? `Could not find clinic with id ${clinicId}, error: ${JSON.stringify(clinicError)}`
|
||||
: `Could not find service with sync id ${serviceSyncId} and clinic id ${clinicId}, error: ${JSON.stringify(serviceError)}`,
|
||||
startTime,
|
||||
serviceSyncId,
|
||||
clinicId,
|
||||
);
|
||||
}
|
||||
|
||||
const clinic: Tables<'connected_online_providers'> = dbClinic![0];
|
||||
const service: Tables<'connected_online_services'> = dbService![0];
|
||||
|
||||
// TODO the dummy data needs to be replaced with real values once they're present on the user/account
|
||||
const response = await axios.post(
|
||||
`${process.env.CONNECTED_ONLINE_URL!}/${ConnectedOnlineMethodName.BookTime}`,
|
||||
{
|
||||
headers: {
|
||||
'Content-Type': 'application/json; charset=utf-8',
|
||||
},
|
||||
param: JSON.stringify({
|
||||
EarlierTime: isEarlierTimeRequested, // once we have the e-shop functionality we can let the user select if she would like to be offered earlier time slots if they become available
|
||||
EarlierTimeComment: earlierTimeRequestComment,
|
||||
ClinicID: clinic.id,
|
||||
ServiceID: service.id,
|
||||
ClinicServiceID: service.sync_id,
|
||||
UserID: appointmentUserId,
|
||||
SyncUserID: syncUserID,
|
||||
StartTime: startTime,
|
||||
FirstName: 'Test',
|
||||
LastName: 'User',
|
||||
PersonalCode: '4',
|
||||
Email: user.email,
|
||||
Phone: 'phone',
|
||||
Comments: comments,
|
||||
Location: locationId,
|
||||
FreeCode: '',
|
||||
AddToBasket: false,
|
||||
Key: '7T624nlu',
|
||||
Lang: 'et', // update when integrated into app, if needed
|
||||
}),
|
||||
},
|
||||
);
|
||||
|
||||
const responseData: BookTimeResponse = JSON.parse(response.data.d);
|
||||
|
||||
if (responseData?.ErrorCode !== 0 || !responseData.Value) {
|
||||
return logRequestResult(
|
||||
ExternalApi.ConnectedOnline,
|
||||
ConnectedOnlineMethodName.BookTime,
|
||||
RequestStatus.Fail,
|
||||
JSON.stringify(responseData),
|
||||
startTime,
|
||||
service.id,
|
||||
clinicId,
|
||||
);
|
||||
}
|
||||
|
||||
const responseParts = responseData.Value.split(',');
|
||||
|
||||
const { error } = await supabase
|
||||
.from('connected_online_reservation')
|
||||
.insert({
|
||||
booking_code: responseParts[1],
|
||||
clinic_id: clinic.id,
|
||||
comments,
|
||||
lang: 'et', // change later, if needed
|
||||
service_id: service.id,
|
||||
service_user_id: appointmentUserId,
|
||||
start_time: startTime,
|
||||
sync_user_id: syncUserID,
|
||||
requires_payment: !!responseParts[0],
|
||||
user_id: user.id,
|
||||
});
|
||||
|
||||
await logRequestResult(
|
||||
ExternalApi.ConnectedOnline,
|
||||
ConnectedOnlineMethodName.BookTime,
|
||||
RequestStatus.Success,
|
||||
JSON.stringify(responseData),
|
||||
startTime,
|
||||
service.id,
|
||||
clinicId,
|
||||
);
|
||||
|
||||
if (error) {
|
||||
throw new Error(error.message);
|
||||
}
|
||||
|
||||
return responseData.Value;
|
||||
} catch (error) {
|
||||
return logRequestResult(
|
||||
ExternalApi.ConnectedOnline,
|
||||
ConnectedOnlineMethodName.BookTime,
|
||||
RequestStatus.Fail,
|
||||
JSON.stringify(error),
|
||||
startTime,
|
||||
serviceSyncId,
|
||||
clinicId,
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
export async function getConfirmedService(reservationCode: string) {
|
||||
try {
|
||||
const response = await axios.post(
|
||||
`${process.env.CONNECTED_ONLINE_URL!}/${ConnectedOnlineMethodName.ConfirmedLoad}`,
|
||||
{
|
||||
headers: {
|
||||
'Content-Type': 'application/json; charset=utf-8',
|
||||
},
|
||||
param: JSON.stringify({ Value: `${reservationCode}|7T624nlu|et` }),
|
||||
},
|
||||
);
|
||||
|
||||
const responseData: ConfirmedLoadResponse = JSON.parse(response.data.d);
|
||||
|
||||
if (responseData?.ErrorCode !== 0) {
|
||||
await logRequestResult(
|
||||
ExternalApi.ConnectedOnline,
|
||||
ConnectedOnlineMethodName.ConfirmedLoad,
|
||||
RequestStatus.Fail,
|
||||
JSON.stringify(responseData),
|
||||
);
|
||||
return null;
|
||||
}
|
||||
|
||||
await logRequestResult(
|
||||
ExternalApi.ConnectedOnline,
|
||||
ConnectedOnlineMethodName.ConfirmedLoad,
|
||||
RequestStatus.Success,
|
||||
JSON.stringify(responseData),
|
||||
);
|
||||
return responseData.Data;
|
||||
} catch (error) {
|
||||
await logRequestResult(
|
||||
ExternalApi.ConnectedOnline,
|
||||
ConnectedOnlineMethodName.ConfirmedLoad,
|
||||
RequestStatus.Fail,
|
||||
JSON.stringify(error),
|
||||
);
|
||||
return null;
|
||||
}
|
||||
}
|
||||
@@ -1,3 +1,5 @@
|
||||
'use server';
|
||||
|
||||
import {
|
||||
SupabaseClient,
|
||||
createClient as createCustomClient,
|
||||
|
||||
Reference in New Issue
Block a user