Newer Version Available
AppointmentBookingInterop Interface
Namespace
Usage
Managing appointments from Health Cloud requires identifying the source system's time slot support; implementing the Health Cloud global AppointmentBookingInterop interface; transforming the input request to fit the source electronic health records (EHR) system; routing the request to the EHR system; and getting the appointment information back from an external appointment booking system.
The external appointment management system is commonly part of a larger electronic health records (EHR) system. The integration between Health Cloud and the EHR can be direct or via integration middleware such as Mulesoft.
The OrgPermissions.HealthCloud permission must be enabled in your Salesforce org to access the Health Cloud AppointmentBookingInterop interface and its methods.
You can use the default implementation AppointmentBookingInteropFhirAdapter provided by Health Cloud to make a call out to an external scheduling system of truth for appointment availability and booking. All communications with the external system use the FHIR 4 standard.
If implementing the default Health Cloud global interface is not right for your context, you can provide your own Apex class and integrate with your appointment management system in your own way. An ISV or a Salesfore partner having Health Cloud license can distribute customized Apex code to your organization using packages.
Use Salesforce platform Named Credentials to configure the class name and authentication for Apex callouts. Then, map the Name Credential name in the AppointmentBookingConfig setup object. The Apex delegator class uses the setup object to invoke the corresponding implementation between the default implementation or your own provided Apex implementation. See Named Credentials as Callout Endpoints in the Apex Developer Guide.
AppointmentBookingInterop Methods
The following are methods for AppointmentBookingInterop.
bookAppointment(var1)
Signature
public healthcloudext.BookAppointmentResponse bookAppointment(healthcloudext.BookAppointmentRequest var1)
Parameters
- var1
- Type: healthcloudext.BookAppointmentRequest
Return Value
cancelAppointment(var1)
Signature
public healthcloudext.CancelAppointmentResponse cancelAppointment(healthcloudext.CancelAppointmentRequest var1)
Parameters
- var1
- Type: healthcloudext.CancelAppointmentRequest
Return Value
findSlots(var1)
Signature
public Map<String,List<healthcloudext.Slot>> findSlots(healthcloudext.FindSlotsRequest var1)
Parameters
- var1
- Type: healthcloudext.FindSlotsRequest
Return Value
Type: Map<String,List<healthcloudext.Slot>>
getSlotStatus(var1)
Signature
public healthcloudext.Slot getSlotStatus(healthcloudext.GetSlotStatusRequest var1)
Parameters
- var1
- Type: healthcloudext.GetSlotStatusRequest
Return Value
Type: healthcloudext.Slot
AppointmentBookingInterop Example Implementation
This is an example implementation of the default class AppointmentBookingInteropFhirAdapter that implements the healthcloudext.AppointmentBookingInterop interface.
1global class AppointmentBookingInteropFhirAdapter implements AppointmentBookingInterop{
2 static final String DEFAULT_ERROR_MESSAGE = 'Error during callout to the external system';
3 static final String DEFAULT_ERROR_CODE = '500';
4
5 /*
6 @Method Name: findSlots
7 @Param: request Type: FindSlotsRequest
8 @Desc: FindSlot implementation
9 */
10 global Map<String,List<Slot>> findSlots(FindSlotsRequest request){
11 Map<String,List<Slot>> response = new Map<String,List<Slot>>();
12 try {
13 HttpRequest httpReq = FindSlotsMapper.mapHttpRequest(request);
14 Http http = new Http();
15 HTTPResponse res = http.send(httpReq);
16 System.debug('Response Body >>>>'+res.getBody());
17 Integer statusCode = res.getStatusCode();
18 if(statusCode == 200) {
19 FHIR.Bundle bundle = FHIRParser.parseSlotBundle(res.getBody());
20 return FindSlotsMapper.mapResponse(request,bundle);
21 } else {
22 processErrorResponse(res);
23 }
24 } catch(AppointmentManagementException e) {
25 throw e;
26 } catch(Exception e){
27 throw new AppointmentManagementException(e.getMessage(), DEFAULT_ERROR_CODE, '', e);
28 }
29 return response;
30 }
31 public void processErrorResponse(HTTPResponse res){
32 try {
33 FHIR.OperationOutcome outcome = FHIRParser.parseOperationOutcome(res.getBody());
34 throw new AppointmentManagementException(getErrorMessage(outcome), String.valueOf(res.getStatusCode()), res.getBody());
35 }catch(Exception e){//If couldn't able to parse to OperationOutcome, issue might be from Middleware
36 if(res.getStatusCode() == 404) {
37 throw new AppointmentManagementException('Find available slots endpoint not found, check the Appointment Booking Config & Appointment Booking URL Config', String.valueOf(res.getStatusCode()), res.getBody());
38 }else {
39 throw new AppointmentManagementException(e.getMessage(), DEFAULT_ERROR_CODE, '');
40 }
41 }
42 }
43 /*
44 @Method Name: bookAppointment
45 @Param: request Type: BookAppointmentRequest
46 @Desc: Book Appointment implementation
47 */
48 global BookAppointmentResponse bookAppointment(BookAppointmentRequest request){
49 BookAppointmentResponse response;
50 try{
51 HttpRequest httpReq = BookAppointmentMapper.mapHttpRequest(request);
52 Http http = new Http();
53 HTTPResponse res = http.send(httpReq);
54 System.debug('Response Body >>>>'+res.getBody());
55 Integer statusCode = res.getStatusCode();
56 if(statusCode == 200 || statusCode == 201) {
57 FHIR.Appointment appointment = FHIRParser.parseAppointment(res.getBody());
58 response = BookAppointmentMapper.mapResponse(request, appointment, res.getBody());
59 } else {
60 FHIR.OperationOutcome outcome = FHIRParser.parseOperationOutcome(res.getBody());
61 throw new AppointmentManagementException(getErrorMessage(outcome), String.valueOf(statusCode), res.getBody());
62 }
63 }catch (Exception e){
64 throw new AppointmentManagementException(DEFAULT_ERROR_MESSAGE, DEFAULT_ERROR_CODE, '');
65 }
66 return response;
67 }
68
69 /*
70 @Method Name: getSlotStatus
71 @Param: request Type: GetSlotStatusRequest
72 @Desc: getSlotStatus implementation
73 */
74 global Slot getSlotStatus(GetSlotStatusRequest request){
75 try{
76 HttpRequest httpReq = GetSlotStatusMapper.mapHttpRequest(request);
77 Http http = new Http();
78 HTTPResponse res = http.send(httpReq);
79 if(res.getStatusCode() == 200) {
80 FHIR.Slot slot = FHIRParser.parseSlot(res.getBody());
81 return GetSlotStatusMapper.mapResponse(slot);
82 }
83 else {
84 FHIR.OperationOutcome outcome = FHIRParser.parseOperationOutcome(res.getBody());
85 throw new AppointmentManagementException(getErrorMessage(outcome), String.valueOf(res.getStatusCode()), res.getBody());
86 }
87 }catch (Exception e){
88 throw new AppointmentManagementException(DEFAULT_ERROR_MESSAGE, DEFAULT_ERROR_CODE, '');
89 }
90 }
91
92 /*
93 @Method Name: cancelAppointment
94 @Param: request Type: CancelAppointmentRequest
95 @Desc: Cancel Appointment implementation
96 */
97 global CancelAppointmentResponse cancelAppointment(CancelAppointmentRequest request){
98 try{
99 HttpRequest httpReq = CancelAppointmentMapper.mapHttpRequest(request);
100 Http http = new Http();
101 HTTPResponse res = http.send(httpReq);
102 System.debug('Response Body >>>>'+res.getBody());
103 Integer statusCode = res.getStatusCode();
104 CancelAppointmentResponse response;
105 if(statusCode == 200 || statusCode == 201) {
106 FHIR.Appointment appointment = FHIRParser.parseAppointment(res.getBody());
107 response = CancelAppointmentMapper.mapResponse( appointment, res.getBody());
108 } else {
109 FHIR.OperationOutcome outcome = FHIRParser.parseOperationOutcome(res.getBody());
110 throw new AppointmentManagementException(getErrorMessage(outcome), String.valueOf(statusCode), res.getBody());
111 }
112 return response;
113 }catch (Exception e){
114 throw new AppointmentManagementException(DEFAULT_ERROR_MESSAGE, DEFAULT_ERROR_CODE, '');
115 }
116 }
117
118 public static String getErrorMessage(FHIR.OperationOutcome outcome){
119 String errorMessage = DEFAULT_ERROR_MESSAGE;
120 if(outcome != null) {
121 if(outcome.issue != null && outcome.issue.size() > 0) {
122 if(outcome.issue[0].details != null && outcome.issue[0].details.text != null) {
123 errorMessage = outcome.issue[0].details.text;
124 } else if(outcome.issue[0].diagnostics != null) {
125 errorMessage = outcome.issue[0].diagnostics;
126 }
127 }
128 }
129 return errorMessage;
130 }
131}