@burgan-tech/morph-touch-runtime 0.0.7 → 0.0.8
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/burgan-tech-morph-touch-runtime-0.0.8.tgz +0 -0
- package/morph-touch/Functions/get-absence-entry.1.0.0.json +1 -1
- package/morph-touch/Functions/get-advisor-stats.1.0.0.json +1 -1
- package/morph-touch/Functions/get-available-slots.1.0.0.json +1 -1
- package/morph-touch/Functions/get-rezervations.1.0.0.json +1 -1
- package/morph-touch/Functions/src/GetAbsenceEntryMapping.csx +18 -4
- package/morph-touch/Functions/src/GetAdvisorStatsMapping.csx +22 -8
- package/morph-touch/Functions/src/GetAvailableSlotsMapping.csx +22 -14
- package/morph-touch/Functions/src/GetRezervationsMapping.csx +19 -2
- package/morph-touch/Functions/src/SendCancelNotificationMapping.csx +27 -2
- package/morph-touch/Tasks/login-for-chat.1.0.0.json +27 -0
- package/morph-touch/Tasks/register-for-chat.1.0.0.json +27 -0
- package/morph-touch/Workflows/chat-room.json +273 -14
- package/morph-touch/Workflows/notification-sender.json +2 -2
- package/morph-touch/Workflows/rezervation-start.json +39 -2
- package/morph-touch/Workflows/rezervation-transfer.json +44 -7
- package/morph-touch/Workflows/rezervation-update.json +4 -4
- package/morph-touch/Workflows/rezervation.json +135 -45
- package/morph-touch/Workflows/src/CanStartRezervationTimerMapping.csx +18 -3
- package/morph-touch/Workflows/src/ChatRoomRemoveMapping.csx +10 -1
- package/morph-touch/Workflows/src/ChatRoomTransferInviteMapping.csx +10 -1
- package/morph-touch/Workflows/src/ChatRoomTransferRemoveMapping.csx +9 -1
- package/morph-touch/Workflows/src/ChatRoomUpdateMapping.csx +10 -1
- package/morph-touch/Workflows/src/CheckDuplicateRezervationMapping.csx +17 -3
- package/morph-touch/Workflows/src/CheckRandevuTimeMapping.csx +16 -2
- package/morph-touch/Workflows/src/CreateChatRoomForRezervationMapping.csx +12 -2
- package/morph-touch/Workflows/src/CreatePermanentChatRoomMapping.csx +11 -1
- package/morph-touch/Workflows/src/EnrichRezervationsForTransferMapping.csx +18 -4
- package/morph-touch/Workflows/src/FetchRoomMessagesForSummaryMapping.csx +10 -2
- package/morph-touch/Workflows/src/InviteAdvisorForRandevuUpdateMapping.csx +10 -1
- package/morph-touch/Workflows/src/InviteNewAdvisorToRezervationRoomMapping.csx +11 -2
- package/morph-touch/Workflows/src/InviteNewParticipantToRandevuRoomMapping.csx +10 -1
- package/morph-touch/Workflows/src/JoinChatRoomForAddParticipantMapping.csx +5 -1
- package/morph-touch/Workflows/src/JoinChatRoomForRandevuStartMapping.csx +5 -1
- package/morph-touch/Workflows/src/JoinChatRoomForRezervationMapping.csx +4 -0
- package/morph-touch/Workflows/src/JoinMatrixRoomMapping.csx +11 -1
- package/morph-touch/Workflows/src/JoinUserToRoomMapping.csx +6 -0
- package/morph-touch/Workflows/src/LoginForAddParticipantChatMapping.csx +35 -6
- package/morph-touch/Workflows/src/LoginForChatRoomMapping.csx +121 -0
- package/morph-touch/Workflows/src/LoginForJoinUserToRoomMapping.csx +142 -0
- package/morph-touch/Workflows/src/LoginForRandevuStartChatMapping.csx +35 -10
- package/morph-touch/Workflows/src/LoginForTransferChatMapping.csx +153 -0
- package/morph-touch/Workflows/src/RegisterForAddParticipantChatMapping.csx +74 -0
- package/morph-touch/Workflows/src/RegisterForChatRoomMapping.csx +74 -0
- package/morph-touch/Workflows/src/RegisterForJoinUserToRoomMapping.csx +87 -0
- package/morph-touch/Workflows/src/RegisterForRandevuStartChatMapping.csx +80 -0
- package/morph-touch/Workflows/src/RegisterForTransferChatMapping.csx +113 -0
- package/morph-touch/Workflows/src/SendPushNotificationMapping.csx +25 -4
- package/morph-touch/Workflows/src/SendSmsNotificationMapping.csx +25 -4
- package/morph-touch/Workflows/src/SendSummaryToNewRoomMapping.csx +10 -2
- package/morph-touch/Workflows/src/SetRoomHistoryVisibilityMapping.csx +12 -4
- package/morph-touch/Workflows/src/ValidateDateForRezervationMapping.csx +16 -2
- package/morph-touch/Workflows/src/ValidateSlotForRandevuUpdateMapping.csx +22 -15
- package/morph-touch/Workflows/src/ValidateSlotForRezervationMapping.csx +23 -16
- package/morph-touch/Workflows/src/ValidateTransferMapping.csx +16 -2
- package/morph-touch/doc/morph-touch-domain.en.md +1 -1
- package/morph-touch/doc/morph-touch-domain.md +1 -1
- package/package.json +1 -1
- package/vnext.config.json +1 -1
- package/burgan-tech-morph-touch-runtime-0.0.7.tgz +0 -0
|
@@ -0,0 +1,80 @@
|
|
|
1
|
+
using System;
|
|
2
|
+
using System.Collections.Generic;
|
|
3
|
+
using System.Threading.Tasks;
|
|
4
|
+
using BBT.Workflow.Scripting;
|
|
5
|
+
using BBT.Workflow.Definitions;
|
|
6
|
+
|
|
7
|
+
/// <summary>
|
|
8
|
+
/// Mapping for register-for-chat in rezervation-start flow.
|
|
9
|
+
/// Registers the user based on participantType (advisor/invited/customer) on Synapse.
|
|
10
|
+
/// ErrorBoundary on the task ignores M_USER_IN_USE and other errors so login proceeds.
|
|
11
|
+
/// </summary>
|
|
12
|
+
public class RegisterForRandevuStartChatMapping : ScriptBase, IMapping
|
|
13
|
+
{
|
|
14
|
+
public async Task<ScriptResponse> InputHandler(WorkflowTask task, ScriptContext context)
|
|
15
|
+
{
|
|
16
|
+
var httpTask = task as HttpTask;
|
|
17
|
+
if (httpTask == null)
|
|
18
|
+
throw new InvalidOperationException("Task must be an HttpTask");
|
|
19
|
+
|
|
20
|
+
var secretName = GetConfigValue("DAPR_SECRET_STORE_NAME");
|
|
21
|
+
if (string.IsNullOrWhiteSpace(secretName))
|
|
22
|
+
throw new InvalidOperationException("DAPR_SECRET_STORE_NAME configuration is required");
|
|
23
|
+
|
|
24
|
+
var matrixBaseUrl = await GetSecretAsync(secretName, "workflow-secret", "MatrixBaseUrl");
|
|
25
|
+
if (string.IsNullOrWhiteSpace(matrixBaseUrl))
|
|
26
|
+
throw new InvalidOperationException("MatrixBaseUrl secret is required");
|
|
27
|
+
|
|
28
|
+
var synapsePassword = await GetSecretAsync(secretName, "workflow-secret", "SynapsePassword");
|
|
29
|
+
if (string.IsNullOrWhiteSpace(synapsePassword))
|
|
30
|
+
throw new InvalidOperationException("SynapsePassword secret is required");
|
|
31
|
+
|
|
32
|
+
var data = context.Instance?.Data;
|
|
33
|
+
var participantType = GetString(data, "participantType");
|
|
34
|
+
var user = GetString(data, "user");
|
|
35
|
+
var advisor = GetString(data, "advisor");
|
|
36
|
+
|
|
37
|
+
var registerUsername = participantType == "advisor" ? advisor
|
|
38
|
+
: participantType == "invited" ? GetString(data, "invitedUserId")
|
|
39
|
+
: "u"+user;
|
|
40
|
+
if (string.IsNullOrWhiteSpace(registerUsername))
|
|
41
|
+
throw new InvalidOperationException("Cannot determine register user: participantType, user, advisor, or invitedUserId missing");
|
|
42
|
+
|
|
43
|
+
var fullUrl = matrixBaseUrl.TrimEnd('/') + "/_matrix/client/v3/register";
|
|
44
|
+
httpTask.SetUrl(fullUrl);
|
|
45
|
+
|
|
46
|
+
httpTask.SetHeaders(new Dictionary<string, string>
|
|
47
|
+
{
|
|
48
|
+
["Content-Type"] = "application/json",
|
|
49
|
+
["Accept"] = "application/json"
|
|
50
|
+
});
|
|
51
|
+
|
|
52
|
+
httpTask.SetBody(new
|
|
53
|
+
{
|
|
54
|
+
auth = new { type = "m.login.dummy" },
|
|
55
|
+
username = registerUsername,
|
|
56
|
+
password = synapsePassword
|
|
57
|
+
});
|
|
58
|
+
return new ScriptResponse();
|
|
59
|
+
}
|
|
60
|
+
|
|
61
|
+
public Task<ScriptResponse> OutputHandler(ScriptContext context)
|
|
62
|
+
{
|
|
63
|
+
return Task.FromResult(new ScriptResponse());
|
|
64
|
+
}
|
|
65
|
+
|
|
66
|
+
private string GetString(dynamic obj, string name)
|
|
67
|
+
{
|
|
68
|
+
if (obj == null) return null;
|
|
69
|
+
try
|
|
70
|
+
{
|
|
71
|
+
if (HasProperty(obj, name))
|
|
72
|
+
{
|
|
73
|
+
var v = GetPropertyValue(obj, name);
|
|
74
|
+
return v?.ToString();
|
|
75
|
+
}
|
|
76
|
+
}
|
|
77
|
+
catch { }
|
|
78
|
+
return null;
|
|
79
|
+
}
|
|
80
|
+
}
|
|
@@ -0,0 +1,113 @@
|
|
|
1
|
+
using System;
|
|
2
|
+
using System.Collections.Generic;
|
|
3
|
+
using System.Linq;
|
|
4
|
+
using System.Threading.Tasks;
|
|
5
|
+
using BBT.Workflow.Scripting;
|
|
6
|
+
using BBT.Workflow.Definitions;
|
|
7
|
+
|
|
8
|
+
/// <summary>
|
|
9
|
+
/// Mapping for register-for-chat in rezervation-transfer flow.
|
|
10
|
+
/// Registers the user looked up from permanentChatRooms by chatRoomKey on Synapse.
|
|
11
|
+
/// ErrorBoundary on the task ignores M_USER_IN_USE and other errors so login proceeds.
|
|
12
|
+
/// </summary>
|
|
13
|
+
public class RegisterForTransferChatMapping : ScriptBase, IMapping
|
|
14
|
+
{
|
|
15
|
+
public async Task<ScriptResponse> InputHandler(WorkflowTask task, ScriptContext context)
|
|
16
|
+
{
|
|
17
|
+
var httpTask = task as HttpTask;
|
|
18
|
+
if (httpTask == null)
|
|
19
|
+
throw new InvalidOperationException("Task must be an HttpTask");
|
|
20
|
+
|
|
21
|
+
var data = context.Instance?.Data;
|
|
22
|
+
if (data == null)
|
|
23
|
+
return new ScriptResponse();
|
|
24
|
+
|
|
25
|
+
string user = null;
|
|
26
|
+
var permanentRoomPlan = data.permanentRoomPlan;
|
|
27
|
+
if (permanentRoomPlan != null)
|
|
28
|
+
{
|
|
29
|
+
int processedIndex = 0;
|
|
30
|
+
if (HasProperty(data, "permanentProcessedIndex"))
|
|
31
|
+
int.TryParse(data.permanentProcessedIndex?.ToString() ?? "0", out processedIndex);
|
|
32
|
+
|
|
33
|
+
var items = permanentRoomPlan as IEnumerable<object>;
|
|
34
|
+
if (items != null)
|
|
35
|
+
{
|
|
36
|
+
var itemsList = items.ToList();
|
|
37
|
+
if (processedIndex < itemsList.Count)
|
|
38
|
+
{
|
|
39
|
+
dynamic currentItem = itemsList[processedIndex];
|
|
40
|
+
var chatRoomKey = currentItem?.chatRoomKey?.ToString();
|
|
41
|
+
if (!string.IsNullOrEmpty(chatRoomKey))
|
|
42
|
+
user = LookupUser(data, chatRoomKey);
|
|
43
|
+
}
|
|
44
|
+
}
|
|
45
|
+
}
|
|
46
|
+
|
|
47
|
+
if (string.IsNullOrWhiteSpace(user))
|
|
48
|
+
return new ScriptResponse();
|
|
49
|
+
|
|
50
|
+
var secretName = GetConfigValue("DAPR_SECRET_STORE_NAME");
|
|
51
|
+
if (string.IsNullOrWhiteSpace(secretName))
|
|
52
|
+
throw new InvalidOperationException("DAPR_SECRET_STORE_NAME configuration is required");
|
|
53
|
+
|
|
54
|
+
var matrixBaseUrl = await GetSecretAsync(secretName, "workflow-secret", "MatrixBaseUrl");
|
|
55
|
+
if (string.IsNullOrWhiteSpace(matrixBaseUrl))
|
|
56
|
+
throw new InvalidOperationException("MatrixBaseUrl secret is required");
|
|
57
|
+
|
|
58
|
+
var synapsePassword = await GetSecretAsync(secretName, "workflow-secret", "SynapsePassword");
|
|
59
|
+
if (string.IsNullOrWhiteSpace(synapsePassword))
|
|
60
|
+
throw new InvalidOperationException("SynapsePassword secret is required");
|
|
61
|
+
|
|
62
|
+
var fullUrl = matrixBaseUrl.TrimEnd('/') + "/_matrix/client/v3/register";
|
|
63
|
+
httpTask.SetUrl(fullUrl);
|
|
64
|
+
|
|
65
|
+
httpTask.SetHeaders(new Dictionary<string, string>
|
|
66
|
+
{
|
|
67
|
+
["Content-Type"] = "application/json",
|
|
68
|
+
["Accept"] = "application/json"
|
|
69
|
+
});
|
|
70
|
+
|
|
71
|
+
httpTask.SetBody(new
|
|
72
|
+
{
|
|
73
|
+
auth = new { type = "m.login.dummy" },
|
|
74
|
+
username = user,
|
|
75
|
+
password = synapsePassword
|
|
76
|
+
});
|
|
77
|
+
return new ScriptResponse();
|
|
78
|
+
}
|
|
79
|
+
|
|
80
|
+
public Task<ScriptResponse> OutputHandler(ScriptContext context)
|
|
81
|
+
{
|
|
82
|
+
return Task.FromResult(new ScriptResponse());
|
|
83
|
+
}
|
|
84
|
+
|
|
85
|
+
private string LookupUser(dynamic data, string chatRoomKey)
|
|
86
|
+
{
|
|
87
|
+
if (!HasProperty(data, "permanentChatRooms") || data.permanentChatRooms == null)
|
|
88
|
+
return null;
|
|
89
|
+
|
|
90
|
+
foreach (var room in data.permanentChatRooms)
|
|
91
|
+
{
|
|
92
|
+
var key = GetString(room, "chatRoomKey");
|
|
93
|
+
if (string.Equals(key, chatRoomKey, StringComparison.OrdinalIgnoreCase))
|
|
94
|
+
return GetString(room, "user");
|
|
95
|
+
}
|
|
96
|
+
return null;
|
|
97
|
+
}
|
|
98
|
+
|
|
99
|
+
private string GetString(dynamic obj, string name)
|
|
100
|
+
{
|
|
101
|
+
if (obj == null) return null;
|
|
102
|
+
try
|
|
103
|
+
{
|
|
104
|
+
if (HasProperty(obj, name))
|
|
105
|
+
{
|
|
106
|
+
var v = GetPropertyValue(obj, name);
|
|
107
|
+
return v?.ToString()?.Trim();
|
|
108
|
+
}
|
|
109
|
+
}
|
|
110
|
+
catch { }
|
|
111
|
+
return null;
|
|
112
|
+
}
|
|
113
|
+
}
|
|
@@ -52,10 +52,7 @@ public class SendPushNotificationMapping : ScriptBase, IMapping
|
|
|
52
52
|
var startDateTime = ctx != null ? GetString(ctx, "startDateTime") : null;
|
|
53
53
|
var reservationKey = ctx != null ? GetString(ctx, "reservationKey") : null;
|
|
54
54
|
|
|
55
|
-
string formattedDate = startDateTime
|
|
56
|
-
DateTime dt = default;
|
|
57
|
-
if (!string.IsNullOrEmpty(startDateTime) && DateTime.TryParse(startDateTime, out dt))
|
|
58
|
-
formattedDate = dt.ToString("dd.MM.yyyy HH:mm");
|
|
55
|
+
string formattedDate = FormatInBusinessTimeZone(startDateTime);
|
|
59
56
|
|
|
60
57
|
string title;
|
|
61
58
|
string content;
|
|
@@ -133,6 +130,30 @@ public class SendPushNotificationMapping : ScriptBase, IMapping
|
|
|
133
130
|
return result;
|
|
134
131
|
}
|
|
135
132
|
|
|
133
|
+
private string FormatInBusinessTimeZone(string dateStr)
|
|
134
|
+
{
|
|
135
|
+
if (string.IsNullOrEmpty(dateStr)) return dateStr ?? "";
|
|
136
|
+
if (!DateTimeOffset.TryParse(dateStr,
|
|
137
|
+
System.Globalization.CultureInfo.InvariantCulture,
|
|
138
|
+
System.Globalization.DateTimeStyles.None, out var dto))
|
|
139
|
+
return dateStr;
|
|
140
|
+
|
|
141
|
+
var tz = ResolveBusinessTimeZone();
|
|
142
|
+
var local = TimeZoneInfo.ConvertTimeFromUtc(dto.UtcDateTime, tz);
|
|
143
|
+
return local.ToString("dd.MM.yyyy HH:mm");
|
|
144
|
+
}
|
|
145
|
+
|
|
146
|
+
private TimeZoneInfo ResolveBusinessTimeZone()
|
|
147
|
+
{
|
|
148
|
+
var id = GetConfigValue("Appointments:TimeZone")
|
|
149
|
+
?? GetConfigValue("APPOINTMENT_TIMEZONE");
|
|
150
|
+
if (string.IsNullOrWhiteSpace(id)) id = "Europe/Istanbul";
|
|
151
|
+
try { return TimeZoneInfo.FindSystemTimeZoneById(id.Trim()); } catch { }
|
|
152
|
+
try { return TimeZoneInfo.FindSystemTimeZoneById("Turkey Standard Time"); } catch { }
|
|
153
|
+
return TimeZoneInfo.CreateCustomTimeZone(
|
|
154
|
+
"TRT", TimeSpan.FromHours(3), "TRT (UTC+3)", "TRT (UTC+3)");
|
|
155
|
+
}
|
|
156
|
+
|
|
136
157
|
private string GetString(dynamic obj, string name)
|
|
137
158
|
{
|
|
138
159
|
if (obj == null) return null;
|
|
@@ -48,10 +48,7 @@ public class SendSmsNotificationMapping : ScriptBase, IMapping
|
|
|
48
48
|
var startDateTime = ctx != null ? GetString(ctx, "startDateTime") : null;
|
|
49
49
|
var reservationKey = ctx != null ? GetString(ctx, "reservationKey") : null;
|
|
50
50
|
|
|
51
|
-
string formattedDate = startDateTime
|
|
52
|
-
DateTime dt = default;
|
|
53
|
-
if (!string.IsNullOrEmpty(startDateTime) && DateTime.TryParse(startDateTime, out dt))
|
|
54
|
-
formattedDate = dt.ToString("dd.MM.yyyy HH:mm");
|
|
51
|
+
string formattedDate = FormatInBusinessTimeZone(startDateTime);
|
|
55
52
|
|
|
56
53
|
string content;
|
|
57
54
|
if (userType == "advisor")
|
|
@@ -125,6 +122,30 @@ public class SendSmsNotificationMapping : ScriptBase, IMapping
|
|
|
125
122
|
return result;
|
|
126
123
|
}
|
|
127
124
|
|
|
125
|
+
private string FormatInBusinessTimeZone(string dateStr)
|
|
126
|
+
{
|
|
127
|
+
if (string.IsNullOrEmpty(dateStr)) return dateStr ?? "";
|
|
128
|
+
if (!DateTimeOffset.TryParse(dateStr,
|
|
129
|
+
System.Globalization.CultureInfo.InvariantCulture,
|
|
130
|
+
System.Globalization.DateTimeStyles.None, out var dto))
|
|
131
|
+
return dateStr;
|
|
132
|
+
|
|
133
|
+
var tz = ResolveBusinessTimeZone();
|
|
134
|
+
var local = TimeZoneInfo.ConvertTimeFromUtc(dto.UtcDateTime, tz);
|
|
135
|
+
return local.ToString("dd.MM.yyyy HH:mm");
|
|
136
|
+
}
|
|
137
|
+
|
|
138
|
+
private TimeZoneInfo ResolveBusinessTimeZone()
|
|
139
|
+
{
|
|
140
|
+
var id = GetConfigValue("Appointments:TimeZone")
|
|
141
|
+
?? GetConfigValue("APPOINTMENT_TIMEZONE");
|
|
142
|
+
if (string.IsNullOrWhiteSpace(id)) id = "Europe/Istanbul";
|
|
143
|
+
try { return TimeZoneInfo.FindSystemTimeZoneById(id.Trim()); } catch { }
|
|
144
|
+
try { return TimeZoneInfo.FindSystemTimeZoneById("Turkey Standard Time"); } catch { }
|
|
145
|
+
return TimeZoneInfo.CreateCustomTimeZone(
|
|
146
|
+
"TRT", TimeSpan.FromHours(3), "TRT (UTC+3)", "TRT (UTC+3)");
|
|
147
|
+
}
|
|
148
|
+
|
|
128
149
|
private string GetString(dynamic obj, string name)
|
|
129
150
|
{
|
|
130
151
|
if (obj == null) return null;
|
|
@@ -69,12 +69,20 @@ public class SendSummaryToNewRoomMapping : ScriptBase, IMapping
|
|
|
69
69
|
"/send/m.room.message/" + txnId;
|
|
70
70
|
|
|
71
71
|
httpTask.SetUrl(fullUrl);
|
|
72
|
-
|
|
72
|
+
|
|
73
|
+
string sessionId = null;
|
|
74
|
+
if (HasProperty(data, "chatIntegration") && data.chatIntegration != null)
|
|
75
|
+
sessionId = GetString(data.chatIntegration, "sessionId");
|
|
76
|
+
|
|
77
|
+
var sendHeaders = new Dictionary<string, string>
|
|
73
78
|
{
|
|
74
79
|
["Content-Type"] = "application/json",
|
|
75
80
|
["Accept"] = "application/json",
|
|
76
81
|
["X-Matrix-User"] = user
|
|
77
|
-
}
|
|
82
|
+
};
|
|
83
|
+
if (!string.IsNullOrWhiteSpace(sessionId))
|
|
84
|
+
sendHeaders["Authorization"] = "Bearer " + sessionId;
|
|
85
|
+
httpTask.SetHeaders(sendHeaders);
|
|
78
86
|
|
|
79
87
|
var messageBody =
|
|
80
88
|
"Onceki danisman ile yapilan gorusme ozeti:\n\n" +
|
|
@@ -43,27 +43,35 @@ public class SetRoomHistoryVisibilityMapping : ScriptBase, IMapping
|
|
|
43
43
|
if (string.IsNullOrWhiteSpace(roomId) || string.IsNullOrWhiteSpace(user))
|
|
44
44
|
return new ScriptResponse();
|
|
45
45
|
|
|
46
|
+
var sessionId = GetString(chatIntegration, "sessionId");
|
|
47
|
+
|
|
46
48
|
if (string.IsNullOrEmpty(hv))
|
|
47
49
|
{
|
|
48
50
|
TrySetHttpMethod(httpTask, "GET");
|
|
49
51
|
httpTask.SetUrl(baseTrim + "/_matrix/client/v3/versions");
|
|
50
|
-
|
|
52
|
+
var noOpHeaders = new Dictionary<string, string>
|
|
51
53
|
{
|
|
52
54
|
["Accept"] = "application/json",
|
|
53
55
|
["X-Matrix-User"] = user
|
|
54
|
-
}
|
|
56
|
+
};
|
|
57
|
+
if (!string.IsNullOrWhiteSpace(sessionId))
|
|
58
|
+
noOpHeaders["Authorization"] = "Bearer " + sessionId;
|
|
59
|
+
httpTask.SetHeaders(noOpHeaders);
|
|
55
60
|
return new ScriptResponse();
|
|
56
61
|
}
|
|
57
62
|
|
|
58
63
|
TrySetHttpMethod(httpTask, "PUT");
|
|
59
64
|
var fullUrl = baseTrim + "/_matrix/client/v3/rooms/" + Uri.EscapeDataString(roomId) + "/state/m.room.history_visibility/";
|
|
60
65
|
httpTask.SetUrl(fullUrl);
|
|
61
|
-
|
|
66
|
+
var putHeaders = new Dictionary<string, string>
|
|
62
67
|
{
|
|
63
68
|
["Content-Type"] = "application/json",
|
|
64
69
|
["Accept"] = "application/json",
|
|
65
70
|
["X-Matrix-User"] = user
|
|
66
|
-
}
|
|
71
|
+
};
|
|
72
|
+
if (!string.IsNullOrWhiteSpace(sessionId))
|
|
73
|
+
putHeaders["Authorization"] = "Bearer " + sessionId;
|
|
74
|
+
httpTask.SetHeaders(putHeaders);
|
|
67
75
|
httpTask.SetBody(new { history_visibility = hv });
|
|
68
76
|
|
|
69
77
|
return new ScriptResponse();
|
|
@@ -23,10 +23,10 @@ public class ValidateDateForRezervationMapping : ScriptBase, IMapping
|
|
|
23
23
|
throw new ArgumentException("startDateTime and endDateTime are required.", "date");
|
|
24
24
|
|
|
25
25
|
DateTime startDt;
|
|
26
|
-
if (!
|
|
26
|
+
if (!TryParseToUtc(startDateTimeStr, out startDt))
|
|
27
27
|
throw new ArgumentException("Invalid startDateTime format.", "startDateTime");
|
|
28
28
|
DateTime endDt;
|
|
29
|
-
if (!
|
|
29
|
+
if (!TryParseToUtc(endDateTimeStr, out endDt))
|
|
30
30
|
throw new ArgumentException("Invalid endDateTime format.", "endDateTime");
|
|
31
31
|
|
|
32
32
|
var now = DateTime.UtcNow;
|
|
@@ -43,6 +43,20 @@ public class ValidateDateForRezervationMapping : ScriptBase, IMapping
|
|
|
43
43
|
return Task.FromResult(new ScriptResponse());
|
|
44
44
|
}
|
|
45
45
|
|
|
46
|
+
private bool TryParseToUtc(string dateStr, out DateTime utcDateTime)
|
|
47
|
+
{
|
|
48
|
+
utcDateTime = default;
|
|
49
|
+
if (string.IsNullOrEmpty(dateStr)) return false;
|
|
50
|
+
if (DateTimeOffset.TryParse(dateStr,
|
|
51
|
+
System.Globalization.CultureInfo.InvariantCulture,
|
|
52
|
+
System.Globalization.DateTimeStyles.None, out var dto))
|
|
53
|
+
{
|
|
54
|
+
utcDateTime = dto.UtcDateTime;
|
|
55
|
+
return true;
|
|
56
|
+
}
|
|
57
|
+
return false;
|
|
58
|
+
}
|
|
59
|
+
|
|
46
60
|
private string GetString(dynamic obj, string name)
|
|
47
61
|
{
|
|
48
62
|
if (obj == null) return null;
|
|
@@ -44,7 +44,7 @@ public class ValidateSlotForRandevuUpdateMapping : ScriptBase, IMapping
|
|
|
44
44
|
}
|
|
45
45
|
|
|
46
46
|
DateTime startDateTime;
|
|
47
|
-
if (!
|
|
47
|
+
if (!TryParseToUtc(startDateTimeStr, out startDateTime))
|
|
48
48
|
{
|
|
49
49
|
return Task.FromResult(new ScriptResponse
|
|
50
50
|
{
|
|
@@ -103,12 +103,12 @@ public class ValidateSlotForRandevuUpdateMapping : ScriptBase, IMapping
|
|
|
103
103
|
});
|
|
104
104
|
}
|
|
105
105
|
|
|
106
|
-
DateTime
|
|
107
|
-
DateTime
|
|
106
|
+
DateTime startDtUtc = DateTime.MinValue;
|
|
107
|
+
DateTime endDtUtc = DateTime.MinValue;
|
|
108
108
|
try
|
|
109
109
|
{
|
|
110
|
-
|
|
111
|
-
|
|
110
|
+
startDtUtc = ParseToUtc(startDateTimeStr);
|
|
111
|
+
endDtUtc = ParseToUtc(endDateTimeStr);
|
|
112
112
|
}
|
|
113
113
|
catch (Exception)
|
|
114
114
|
{
|
|
@@ -119,8 +119,8 @@ public class ValidateSlotForRandevuUpdateMapping : ScriptBase, IMapping
|
|
|
119
119
|
}
|
|
120
120
|
|
|
121
121
|
var tz = ResolveBusinessTimeZone();
|
|
122
|
-
var localStart =
|
|
123
|
-
var localEnd =
|
|
122
|
+
var localStart = TimeZoneInfo.ConvertTimeFromUtc(startDtUtc, tz);
|
|
123
|
+
var localEnd = TimeZoneInfo.ConvertTimeFromUtc(endDtUtc, tz);
|
|
124
124
|
var requestedSlot = localStart.ToString("HH:mm") + "-" + localEnd.ToString("HH:mm");
|
|
125
125
|
bool available = false;
|
|
126
126
|
string responseKey = null;
|
|
@@ -208,18 +208,25 @@ public class ValidateSlotForRandevuUpdateMapping : ScriptBase, IMapping
|
|
|
208
208
|
return TimeZoneInfo.CreateCustomTimeZone("TRT", TimeSpan.FromHours(3), "TRT (UTC+3)", "TRT (UTC+3)");
|
|
209
209
|
}
|
|
210
210
|
|
|
211
|
-
private
|
|
211
|
+
private bool TryParseToUtc(string dateStr, out DateTime utcDateTime)
|
|
212
212
|
{
|
|
213
|
-
|
|
214
|
-
|
|
215
|
-
|
|
216
|
-
|
|
213
|
+
utcDateTime = default;
|
|
214
|
+
if (string.IsNullOrEmpty(dateStr)) return false;
|
|
215
|
+
if (DateTimeOffset.TryParse(dateStr,
|
|
216
|
+
System.Globalization.CultureInfo.InvariantCulture,
|
|
217
|
+
System.Globalization.DateTimeStyles.None, out var dto))
|
|
217
218
|
{
|
|
218
|
-
|
|
219
|
-
return
|
|
219
|
+
utcDateTime = dto.UtcDateTime;
|
|
220
|
+
return true;
|
|
220
221
|
}
|
|
222
|
+
return false;
|
|
223
|
+
}
|
|
221
224
|
|
|
222
|
-
|
|
225
|
+
private DateTime ParseToUtc(string dateStr)
|
|
226
|
+
{
|
|
227
|
+
var dto = DateTimeOffset.Parse(dateStr,
|
|
228
|
+
System.Globalization.CultureInfo.InvariantCulture);
|
|
229
|
+
return dto.UtcDateTime;
|
|
223
230
|
}
|
|
224
231
|
|
|
225
232
|
private string GetString(dynamic obj, string name)
|
|
@@ -49,7 +49,7 @@ public class ValidateSlotForRezervationMapping : ScriptBase, IMapping
|
|
|
49
49
|
}
|
|
50
50
|
|
|
51
51
|
DateTime startDateTime;
|
|
52
|
-
if (!
|
|
52
|
+
if (!TryParseToUtc(startDateTimeStr, out startDateTime))
|
|
53
53
|
{
|
|
54
54
|
return Task.FromResult(new ScriptResponse
|
|
55
55
|
{
|
|
@@ -119,14 +119,14 @@ public class ValidateSlotForRezervationMapping : ScriptBase, IMapping
|
|
|
119
119
|
});
|
|
120
120
|
}
|
|
121
121
|
|
|
122
|
-
DateTime
|
|
123
|
-
DateTime
|
|
122
|
+
DateTime startDtUtc = DateTime.MinValue;
|
|
123
|
+
DateTime endDtUtc = DateTime.MinValue;
|
|
124
124
|
try
|
|
125
125
|
{
|
|
126
|
-
|
|
127
|
-
|
|
126
|
+
startDtUtc = ParseToUtc(startDateTimeStr);
|
|
127
|
+
endDtUtc = ParseToUtc(endDateTimeStr);
|
|
128
128
|
}
|
|
129
|
-
catch (Exception
|
|
129
|
+
catch (Exception)
|
|
130
130
|
{
|
|
131
131
|
return Task.FromResult(new ScriptResponse
|
|
132
132
|
{
|
|
@@ -135,8 +135,8 @@ public class ValidateSlotForRezervationMapping : ScriptBase, IMapping
|
|
|
135
135
|
}
|
|
136
136
|
|
|
137
137
|
var tz = ResolveBusinessTimeZone();
|
|
138
|
-
var localStart =
|
|
139
|
-
var localEnd =
|
|
138
|
+
var localStart = TimeZoneInfo.ConvertTimeFromUtc(startDtUtc, tz);
|
|
139
|
+
var localEnd = TimeZoneInfo.ConvertTimeFromUtc(endDtUtc, tz);
|
|
140
140
|
var requestedSlot = localStart.ToString("HH:mm") + "-" + localEnd.ToString("HH:mm");
|
|
141
141
|
|
|
142
142
|
bool available = false;
|
|
@@ -243,18 +243,25 @@ public class ValidateSlotForRezervationMapping : ScriptBase, IMapping
|
|
|
243
243
|
return TimeZoneInfo.CreateCustomTimeZone("TRT", TimeSpan.FromHours(3), "TRT (UTC+3)", "TRT (UTC+3)");
|
|
244
244
|
}
|
|
245
245
|
|
|
246
|
-
private
|
|
246
|
+
private bool TryParseToUtc(string dateStr, out DateTime utcDateTime)
|
|
247
247
|
{
|
|
248
|
-
|
|
249
|
-
|
|
250
|
-
|
|
251
|
-
|
|
248
|
+
utcDateTime = default;
|
|
249
|
+
if (string.IsNullOrEmpty(dateStr)) return false;
|
|
250
|
+
if (DateTimeOffset.TryParse(dateStr,
|
|
251
|
+
System.Globalization.CultureInfo.InvariantCulture,
|
|
252
|
+
System.Globalization.DateTimeStyles.None, out var dto))
|
|
252
253
|
{
|
|
253
|
-
|
|
254
|
-
return
|
|
254
|
+
utcDateTime = dto.UtcDateTime;
|
|
255
|
+
return true;
|
|
255
256
|
}
|
|
257
|
+
return false;
|
|
258
|
+
}
|
|
256
259
|
|
|
257
|
-
|
|
260
|
+
private DateTime ParseToUtc(string dateStr)
|
|
261
|
+
{
|
|
262
|
+
var dto = DateTimeOffset.Parse(dateStr,
|
|
263
|
+
System.Globalization.CultureInfo.InvariantCulture);
|
|
264
|
+
return dto.UtcDateTime;
|
|
258
265
|
}
|
|
259
266
|
|
|
260
267
|
private string GetString(dynamic obj, string name)
|
|
@@ -125,7 +125,7 @@ public class ValidateTransferMapping : ScriptBase, IMapping
|
|
|
125
125
|
|
|
126
126
|
DateTime rezStart = DateTime.MinValue;
|
|
127
127
|
DateTime rezEnd = DateTime.MinValue;
|
|
128
|
-
if (!
|
|
128
|
+
if (!TryParseToUtc(rezStartStr, out rezStart) || !TryParseToUtc(rezEndStr, out rezEnd))
|
|
129
129
|
{
|
|
130
130
|
details.Add(new { rezervationKey, targetAdvisor, valid = true, reason = "unparseable-time" });
|
|
131
131
|
continue;
|
|
@@ -151,7 +151,7 @@ public class ValidateTransferMapping : ScriptBase, IMapping
|
|
|
151
151
|
|
|
152
152
|
DateTime itemStart = DateTime.MinValue;
|
|
153
153
|
DateTime itemEnd = DateTime.MinValue;
|
|
154
|
-
if (
|
|
154
|
+
if (TryParseToUtc(itemStartStr, out itemStart) && TryParseToUtc(itemEndStr, out itemEnd))
|
|
155
155
|
{
|
|
156
156
|
var itemKey = HasProperty(item, "key") ? item.key?.ToString() : "";
|
|
157
157
|
if (itemKey == rezervationKey) continue;
|
|
@@ -206,6 +206,20 @@ public class ValidateTransferMapping : ScriptBase, IMapping
|
|
|
206
206
|
}
|
|
207
207
|
}
|
|
208
208
|
|
|
209
|
+
private bool TryParseToUtc(string dateStr, out DateTime utcDateTime)
|
|
210
|
+
{
|
|
211
|
+
utcDateTime = default;
|
|
212
|
+
if (string.IsNullOrEmpty(dateStr)) return false;
|
|
213
|
+
if (DateTimeOffset.TryParse(dateStr,
|
|
214
|
+
System.Globalization.CultureInfo.InvariantCulture,
|
|
215
|
+
System.Globalization.DateTimeStyles.None, out var dto))
|
|
216
|
+
{
|
|
217
|
+
utcDateTime = dto.UtcDateTime;
|
|
218
|
+
return true;
|
|
219
|
+
}
|
|
220
|
+
return false;
|
|
221
|
+
}
|
|
222
|
+
|
|
209
223
|
private string GetString(dynamic obj, string name)
|
|
210
224
|
{
|
|
211
225
|
if (obj == null) return null;
|
|
@@ -339,7 +339,7 @@ For appointments and **get-available-slots**, define **company working hours** f
|
|
|
339
339
|
- In all examples, **`{{BaseUrl}}`** is your API gateway **root** (e.g. `https://<host>` or `https://<host>/ebanking` depending on deployment). Set it per APISIX / environment docs; avoid a trailing slash on the root or you may get **double slashes** (`//morph-touch`) when concatenating.
|
|
340
340
|
- Standard template: **`{{BaseUrl}}/morph-touch/workflows/...`** and **`{{BaseUrl}}/morph-touch/functions/...`** (e.g. `{{BaseUrl}}/morph-touch/workflows/absence-entry/instances/start?sync=true`).
|
|
341
341
|
- This matches the role of Postman’s `{{baseUrl}}`; this doc uses the name **`{{BaseUrl}}`**.
|
|
342
|
-
- **`Authorization: Bearer <access_token>`:** The access token is **environment-specific** (dev, test, production). Obtain it from your identity provider or whatever process your environment documents (APISIX, API portal, security team). `<access_token>` in examples is only a placeholder; never commit real tokens to the repo or shared docs.
|
|
342
|
+
- **`Authorization: Bearer <access_token>`:** In many setups this header is **required**; whether it is mandatory can **vary by environment** (e.g. local dev may omit it per policy). The access token itself is **environment-specific** (dev, test, production). Obtain it from your identity provider or whatever process your environment documents (APISIX, API portal, security team). `<access_token>` in examples is only a placeholder; never commit real tokens to the repo or shared docs.
|
|
343
343
|
- In `.../workflows/{flowKey}/instances/<segment>/...`, `<segment>` is **`{{instanceIdOrKey}}`**: either the platform **instance id** or the instance **`key`**.
|
|
344
344
|
|
|
345
345
|
### 14.3 Company working hours — `absence-entry` start (once)
|
|
@@ -339,7 +339,7 @@ Randevu ve **get-available-slots** mantığı için önce **şirket çalışma s
|
|
|
339
339
|
- Tüm örneklerde **`{{BaseUrl}}`**, ortamınızdaki API gateway **kökünü** temsil eder (örneğin `https://<host>` veya kurulumunuza göre `https://<host>/ebanking`). Değeri APISIX / ortam dokümantasyonunuza göre ayarlayın; kökün sonunda `/` bırakmayın veya birleştirmede **çift slash** (`//morph-touch`) oluşmamasına dikkat edin.
|
|
340
340
|
- Standart şablon: **`{{BaseUrl}}/morph-touch/workflows/...`** ve **`{{BaseUrl}}/morph-touch/functions/...`** (örnek: `{{BaseUrl}}/morph-touch/workflows/absence-entry/instances/start?sync=true`).
|
|
341
341
|
- Postman koleksiyonundaki `{{baseUrl}}` ile aynı rolde düşünülebilir; isimlendirme dokümanda `{{BaseUrl}}` olarak verilmiştir.
|
|
342
|
-
- **`Authorization: Bearer <access_token>`:** Erişim jetonu **ortama göre**
|
|
342
|
+
- **`Authorization: Bearer <access_token>`:** Birçok ortamda bu başlık **zorunludur**; gateway veya güvenlik politikasına göre zorunluluk **ortamdan ortama değişebilir** (yerel geliştirme hariç tutulabilir). Erişim jetonu **ortama göre** alınır (geliştirme, test, üretim). Token’ı ilgili kimlik sağlayıcısından veya ortamınızın (APISIX, API portalı, güvenlik ekibi) verdiği yöntemle edinin; örneklerdeki `<access_token>` yalnızca yer tutucudur. Gerçek token’ları repoya veya paylaşılan dokümana yapıştırmayın.
|
|
343
343
|
- `.../workflows/{flowKey}/instances/<segment>/...` adresindeki `<segment>`: **`{{instanceIdOrKey}}`** — ya platformun döndüğü **instance id** ya da instance **`key`** değeridir.
|
|
344
344
|
|
|
345
345
|
### 14.3 Şirket çalışma saatleri — `absence-entry` start (tek sefer)
|
package/package.json
CHANGED
package/vnext.config.json
CHANGED
|
Binary file
|