diff --git a/.vs/BMA.EHR.Recruit.Service/v17/.suo b/.vs/BMA.EHR.Recruit.Service/v17/.suo
index 2099b8b..4e2d5f4 100644
Binary files a/.vs/BMA.EHR.Recruit.Service/v17/.suo and b/.vs/BMA.EHR.Recruit.Service/v17/.suo differ
diff --git a/BMA.EHR.Recruit.Service.csproj b/BMA.EHR.Recruit.Service.csproj
index cde6d16..d2ebf6a 100644
--- a/BMA.EHR.Recruit.Service.csproj
+++ b/BMA.EHR.Recruit.Service.csproj
@@ -38,6 +38,7 @@
+
diff --git a/BMA.EHR.Recruit.Service.csproj.user b/BMA.EHR.Recruit.Service.csproj.user
index c404400..25fe956 100644
--- a/BMA.EHR.Recruit.Service.csproj.user
+++ b/BMA.EHR.Recruit.Service.csproj.user
@@ -1,9 +1,9 @@
-
-
-
- https
-
-
- ProjectDebugger
-
+
+
+
+ dotnet
+
+
+ ProjectDebugger
+
\ No newline at end of file
diff --git a/Core/DateTimeFixConverter.cs b/Core/DateTimeFixConverter.cs
new file mode 100644
index 0000000..60c8af6
--- /dev/null
+++ b/Core/DateTimeFixConverter.cs
@@ -0,0 +1,25 @@
+using System.Text.Json;
+using System.Text.Json.Serialization;
+
+namespace BMA.EHR.Recruit.Service.Core
+{
+ public class DateTimeFixConverter : JsonConverter
+ {
+ public override DateTime Read(ref Utf8JsonReader reader, Type typeToConvert, JsonSerializerOptions options)
+ {
+ if (reader.TokenType == JsonTokenType.String)
+ {
+ if (DateTime.TryParse(reader.GetString(), out var date))
+ {
+ return date;
+ }
+ }
+ throw new JsonException("Invalid date format.");
+ }
+
+ public override void Write(Utf8JsonWriter writer, DateTime value, JsonSerializerOptions options)
+ {
+ writer.WriteStringValue(value.ToString("yyyy-MM-dd"));
+ }
+ }
+}
diff --git a/Core/RequestLoggingMiddleware.cs b/Core/RequestLoggingMiddleware.cs
new file mode 100644
index 0000000..69a8d3b
--- /dev/null
+++ b/Core/RequestLoggingMiddleware.cs
@@ -0,0 +1,264 @@
+using Microsoft.AspNetCore.Http;
+using Microsoft.Extensions.Configuration;
+using Nest;
+using Newtonsoft.Json;
+using System.Diagnostics;
+using System.Net.Http.Headers;
+using System.Security.Claims;
+using System.Text.Encodings.Web;
+using System.Text.Json;
+using JsonSerializer = System.Text.Json.JsonSerializer;
+
+namespace BMA.EHR.Recruit.Service.Core
+{
+ public class RequestLoggingMiddleware
+ {
+ private readonly RequestDelegate _next;
+ private readonly IConfiguration _configuration;
+
+ private string Uri = "";
+ private string IndexFormat = "";
+ private string SystemName = "";
+ private string APIKey = "";
+
+ public RequestLoggingMiddleware(RequestDelegate next, IConfiguration configuration)
+ {
+ _next = next;
+ _configuration = configuration;
+
+ Uri = _configuration["ElasticConfiguration:Uri"] ?? "http://192.168.1.40:9200";
+ IndexFormat = _configuration["ElasticConfiguration:IndexFormat"] ?? "bma-ehr-log-index";
+ SystemName = _configuration["ElasticConfiguration:SystemName"] ?? "Unknown";
+ }
+
+ protected async Task GetExternalAPIAsync(string apiPath, string accessToken, string apiKey)
+ {
+ try
+ {
+ using (var client = new HttpClient())
+ {
+ client.DefaultRequestHeaders.Authorization = new AuthenticationHeaderValue("Bearer", accessToken.Replace("Bearer ", ""));
+ client.DefaultRequestHeaders.Add("api_key", apiKey);
+ var _res = await client.GetAsync(apiPath);
+ if (_res.IsSuccessStatusCode)
+ {
+ var _result = await _res.Content.ReadAsStringAsync();
+
+ return _result;
+ }
+ return string.Empty;
+ }
+ }
+ catch
+ {
+ throw;
+ }
+ }
+
+ public async Task GetProfileByKeycloakIdAsync(Guid keycloakId, string? accessToken)
+ {
+ try
+ {
+ var apiPath = $"{_configuration["API"]}/org/dotnet/keycloak/{keycloakId}";
+ var apiKey = _configuration["API_KEY"];
+
+ var apiResult = await GetExternalAPIAsync(apiPath, accessToken ?? "", apiKey);
+ if (apiResult != null)
+ {
+ var raw = JsonConvert.DeserializeObject(apiResult);
+ if (raw != null)
+ return raw.Result;
+ }
+
+ return null;
+ }
+ catch
+ {
+ throw;
+ }
+ }
+
+ public async Task Invoke(HttpContext context)
+ {
+ var settings = new ConnectionSettings(new Uri(Uri))
+ .DefaultIndex(IndexFormat);
+
+ var client = new ElasticClient(settings);
+
+
+ var startTime = DateTime.UtcNow;
+ var stopwatch = Stopwatch.StartNew();
+ string? responseBodyJson = null;
+ string? requestBodyJson = null;
+
+ string requestBody = await ReadRequestBodyAsync(context);
+ if (requestBody != "")
+ {
+ if (context.Request.HasFormContentType)
+ {
+ var form = await context.Request.ReadFormAsync(); // อ่าน form-data
+
+ var formData = new Dictionary();
+ foreach (var field in form)
+ {
+ formData[field.Key] = field.Value.ToString();
+ }
+ // อ่านไฟล์ที่ถูกส่งมา (ถ้ามี)
+ if (form.Files.Count > 0)
+ {
+ var fileDataList = new List