Skip to content

Commit 969ee61

Browse files
committed
[ACTION] Microsoft Booking - new components
1 parent e211496 commit 969ee61

File tree

13 files changed

+1314
-22
lines changed

13 files changed

+1314
-22
lines changed
Lines changed: 64 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,64 @@
1+
import app from "../../microsoft_bookings.app.mjs";
2+
3+
export default {
4+
key: "microsoft_bookings-cancel-appointment",
5+
name: "Cancel Appointment",
6+
description: "Cancels an appointment in a Microsoft Bookings business. [See the documentation](https://learn.microsoft.com/en-us/graph/api/bookingappointment-cancel?view=graph-rest-1.0)",
7+
version: "0.0.1",
8+
type: "action",
9+
annotations: {
10+
readOnlyHint: false,
11+
destructiveHint: true,
12+
openWorldHint: true,
13+
},
14+
props: {
15+
app,
16+
businessId: {
17+
propDefinition: [
18+
app,
19+
"businessId",
20+
],
21+
},
22+
appointmentId: {
23+
propDefinition: [
24+
app,
25+
"appointmentId",
26+
({ businessId }) => ({
27+
businessId,
28+
}),
29+
],
30+
},
31+
cancellationMessage: {
32+
type: "string",
33+
label: "Cancellation Message",
34+
description: "A message to send to the customer and staff members about the cancellation",
35+
},
36+
},
37+
async run({ $ }) {
38+
const {
39+
app,
40+
businessId,
41+
appointmentId,
42+
cancellationMessage,
43+
} = this;
44+
45+
try {
46+
await app.cancelAppointment({
47+
businessId,
48+
appointmentId,
49+
content: {
50+
cancellationMessage,
51+
},
52+
});
53+
54+
$.export("$summary", "Successfully cancelled appointment");
55+
56+
return {
57+
success: true,
58+
};
59+
} catch (error) {
60+
throw new Error("Failed to cancel appointment, you must provide a cancellation message");
61+
}
62+
63+
},
64+
};
Lines changed: 286 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,286 @@
1+
import app from "../../microsoft_bookings.app.mjs";
2+
3+
export default {
4+
key: "microsoft_bookings-create-appointment",
5+
name: "Create Appointment",
6+
description: "Creates a new appointment in a Microsoft Bookings business. [See the documentation](https://learn.microsoft.com/en-us/graph/api/bookingbusiness-post-appointments?view=graph-rest-1.0)",
7+
version: "0.0.1",
8+
type: "action",
9+
annotations: {
10+
readOnlyHint: false,
11+
destructiveHint: false,
12+
openWorldHint: true,
13+
},
14+
props: {
15+
app,
16+
businessId: {
17+
propDefinition: [
18+
app,
19+
"businessId",
20+
],
21+
},
22+
serviceId: {
23+
propDefinition: [
24+
app,
25+
"serviceId",
26+
({ businessId }) => ({
27+
businessId,
28+
}),
29+
],
30+
},
31+
customerId: {
32+
propDefinition: [
33+
app,
34+
"staffMemberId",
35+
({ businessId }) => ({
36+
businessId,
37+
}),
38+
],
39+
label: "Customer ID",
40+
description: "Select an existing customer. **Important**: Customers must exist in the system before booking appointments.",
41+
},
42+
customerName: {
43+
type: "string",
44+
label: "Customer Name",
45+
description: "The name of the customer",
46+
optional: true,
47+
},
48+
customerEmailAddress: {
49+
type: "string",
50+
label: "Customer Email Address",
51+
description: "The SMTP address of the customer",
52+
optional: true,
53+
},
54+
customerTimeZone: {
55+
type: "string",
56+
label: "Customer Time Zone",
57+
description: "The customer's time zone (e.g., America/Chicago, UTC)",
58+
optional: true,
59+
},
60+
startDateTime: {
61+
type: "string",
62+
label: "Start Date Time",
63+
description: "The date and time when the appointment begins in ISO 8601 format (e.g., 2024-05-01T12:00:00)",
64+
},
65+
endDateTime: {
66+
type: "string",
67+
label: "End Date Time",
68+
description: "The date and time when the appointment ends in ISO 8601 format (e.g., 2024-05-01T13:00:00)",
69+
},
70+
timeZone: {
71+
type: "string",
72+
label: "Time Zone",
73+
description: "The time zone for the appointment (e.g., UTC, America/Chicago)",
74+
},
75+
customerPhone: {
76+
type: "string",
77+
label: "Customer Phone",
78+
description: "The phone number of the customer",
79+
optional: true,
80+
},
81+
customerNotes: {
82+
type: "string",
83+
label: "Customer Notes",
84+
description: "Notes from the customer associated with this appointment",
85+
optional: true,
86+
},
87+
isLocationOnline: {
88+
type: "boolean",
89+
label: "Is Location Online",
90+
description: "True indicates that the appointment will be held online",
91+
optional: true,
92+
},
93+
staffMemberIds: {
94+
type: "string[]",
95+
label: "Staff Member IDs",
96+
description: "The IDs of each staff member who is scheduled in this appointment",
97+
optional: true,
98+
propDefinition: [
99+
app,
100+
"staffMemberId",
101+
({ businessId }) => ({
102+
businessId,
103+
}),
104+
],
105+
},
106+
smsNotificationsEnabled: {
107+
type: "boolean",
108+
label: "SMS Notifications Enabled",
109+
description: "If SMS notifications will be sent to the customers for the appointment",
110+
optional: true,
111+
},
112+
price: {
113+
type: "string",
114+
label: "Price",
115+
description: "The regular price for the appointment",
116+
optional: true,
117+
},
118+
priceType: {
119+
type: "string",
120+
label: "Price Type",
121+
description: "The pricing structure for the appointment",
122+
optional: true,
123+
options: [
124+
"undefined",
125+
"fixedPrice",
126+
"startingAt",
127+
"hourly",
128+
"free",
129+
"priceVaries",
130+
"callUs",
131+
"notSet",
132+
],
133+
},
134+
duration: {
135+
type: "string",
136+
label: "Duration",
137+
description: "The length of the appointment in ISO 8601 format (e.g., PT1H for 1 hour, PT30M for 30 minutes). If not specified, calculated from start/end times.",
138+
optional: true,
139+
},
140+
maximumAttendeesCount: {
141+
type: "integer",
142+
label: "Maximum Attendees Count",
143+
description: "The maximum number of customers allowed in this appointment",
144+
optional: true,
145+
},
146+
preBuffer: {
147+
type: "string",
148+
label: "Pre-Buffer",
149+
description: "Time to reserve before the appointment in ISO 8601 format (e.g., PT15M for 15 minutes)",
150+
optional: true,
151+
},
152+
postBuffer: {
153+
type: "string",
154+
label: "Post-Buffer",
155+
description: "Time to reserve after the appointment in ISO 8601 format (e.g., PT15M for 15 minutes)",
156+
optional: true,
157+
},
158+
serviceNotes: {
159+
type: "string",
160+
label: "Service Notes",
161+
description: "Notes from the staff member about this appointment",
162+
optional: true,
163+
},
164+
additionalInformation: {
165+
type: "string",
166+
label: "Additional Information",
167+
description: "Additional information sent to the customer when the appointment is confirmed",
168+
optional: true,
169+
},
170+
isCustomerAllowedToManageBooking: {
171+
type: "boolean",
172+
label: "Customer Can Manage Booking",
173+
description: "Indicates that the customer can manage bookings created by the staff",
174+
optional: true,
175+
},
176+
optOutOfCustomerEmail: {
177+
type: "boolean",
178+
label: "Opt Out of Customer Email",
179+
description: "If true, the customer doesn't wish to receive a confirmation for this appointment",
180+
optional: true,
181+
},
182+
},
183+
async run({ $ }) {
184+
const {
185+
app,
186+
businessId,
187+
serviceId,
188+
customerId,
189+
customerName,
190+
customerEmailAddress,
191+
customerTimeZone,
192+
startDateTime,
193+
endDateTime,
194+
timeZone,
195+
customerPhone,
196+
customerNotes,
197+
isLocationOnline,
198+
staffMemberIds,
199+
smsNotificationsEnabled,
200+
price,
201+
priceType,
202+
duration,
203+
maximumAttendeesCount,
204+
preBuffer,
205+
postBuffer,
206+
serviceNotes,
207+
additionalInformation,
208+
isCustomerAllowedToManageBooking,
209+
optOutOfCustomerEmail,
210+
} = this;
211+
212+
if (!customerId) {
213+
throw new Error("Customer ID is required. Please select an existing customer.");
214+
}
215+
216+
const content = {
217+
"@odata.type": "#microsoft.graph.bookingAppointment",
218+
"serviceId": serviceId,
219+
"customerTimeZone": customerTimeZone || timeZone,
220+
"startDateTime": {
221+
"@odata.type": "#microsoft.graph.dateTimeTimeZone",
222+
"dateTime": startDateTime,
223+
"timeZone": timeZone,
224+
},
225+
"endDateTime": {
226+
"@odata.type": "#microsoft.graph.dateTimeTimeZone",
227+
"dateTime": endDateTime,
228+
"timeZone": timeZone,
229+
},
230+
"customers": [
231+
{
232+
"@odata.type": "#microsoft.graph.bookingCustomerInformation",
233+
"customerId": customerId,
234+
...(customerName && {
235+
"name": customerName,
236+
}),
237+
...(customerEmailAddress && {
238+
"emailAddress": customerEmailAddress,
239+
}),
240+
...(customerPhone && {
241+
"phone": customerPhone,
242+
}),
243+
"timeZone": customerTimeZone || timeZone,
244+
},
245+
],
246+
};
247+
248+
if (customerNotes) content.customerNotes = customerNotes;
249+
if (isLocationOnline !== undefined) {
250+
content.isLocationOnline = isLocationOnline;
251+
}
252+
if (staffMemberIds?.length > 0) content.staffMemberIds = staffMemberIds;
253+
if (smsNotificationsEnabled !== undefined) {
254+
content.smsNotificationsEnabled = smsNotificationsEnabled;
255+
}
256+
if (price) content.price = parseFloat(price);
257+
if (priceType) content.priceType = priceType;
258+
if (duration) content.duration = duration;
259+
if (maximumAttendeesCount) content.maximumAttendeesCount = maximumAttendeesCount;
260+
if (preBuffer) content.preBuffer = preBuffer;
261+
if (postBuffer) content.postBuffer = postBuffer;
262+
if (serviceNotes) content.serviceNotes = serviceNotes;
263+
if (additionalInformation) content.additionalInformation = additionalInformation;
264+
if (isCustomerAllowedToManageBooking !== undefined) {
265+
content.isCustomerAllowedToManageBooking = isCustomerAllowedToManageBooking;
266+
}
267+
if (optOutOfCustomerEmail !== undefined) {
268+
content.optOutOfCustomerEmail = optOutOfCustomerEmail;
269+
}
270+
271+
try {
272+
const response = await app.createAppointment({
273+
businessId,
274+
content,
275+
});
276+
277+
$.export("$summary", `Successfully created appointment for ${customerName}`);
278+
279+
return response;
280+
} catch (error) {
281+
console.error("Error creating appointment:", error);
282+
console.error("Request payload:", JSON.stringify(content, null, 2));
283+
throw new Error(`Failed to create appointment: ${error.message || error.toString()}`);
284+
}
285+
},
286+
};

0 commit comments

Comments
 (0)