Add store log analysis feature and related data structures

- Implement AnalyzeSlotUnregistrationsAsync method to retrieve and report store log data for cooperating stores in region 139.
- Introduce StoreLogProfileEntry record to aggregate log information.
- Add StoreLog endpoint for API access.
- Create GetStoreLogAsync and GetStoreLogEntriesAsync methods for fetching and deserializing store log entries.
- Update Program.cs to include the new analysis task option.
This commit is contained in:
a.beging
2026-01-27 20:30:52 +01:00
parent 516fceb1dc
commit ada7f979cf
6 changed files with 207 additions and 8 deletions

View File

@@ -82,6 +82,68 @@ namespace FsToolbox.Cli.Tasks
#endregion
#region Public Method GetStoreLogAsync
/// <summary>
/// Retrieves the store log for a specified store and date range.
/// </summary>
/// <param name="httpClient">The HTTP client used to send the request.</param>
/// <param name="storeId">The store identifier to query.</param>
/// <param name="fromDate">Start date (formatted for the API).</param>
/// <param name="toDate">End date (formatted for the API).</param>
/// <param name="storeLogActionIds">Comma-separated action IDs.</param>
/// <returns>The raw response body from the API.</returns>
public static async Task<string> GetStoreLogAsync(HttpClient httpClient, int storeId, string fromDate, string toDate, string storeLogActionIds)
{
await AuthHelper.EnsureAuthenticationAsync(httpClient);
var uri = string.Format(Endpoints.StoreLog, storeId, fromDate, toDate, storeLogActionIds);
var response = await httpClient.GetAsync(uri);
var responseBody = await response.Content.ReadAsStringAsync();
// handle unsuccessful response
if (!response.IsSuccessStatusCode)
Logger.Error("Store log retrieval failed ({Status} {Reason}): {Body}", (int)response.StatusCode, response.ReasonPhrase, responseBody);
return responseBody;
}
#endregion
#region Public Method GetStoreLogEntriesAsync
/// <summary>
/// Retrieves and deserializes store log entries for a specified store and date range.
/// </summary>
/// <param name="httpClient">The HTTP client used to send the request.</param>
/// <param name="storeId">The store identifier to query.</param>
/// <param name="fromDate">Start date (formatted for the API).</param>
/// <param name="toDate">End date (formatted for the API).</param>
/// <param name="storeLogActionIds">Comma-separated action IDs.</param>
/// <returns>A list of store log entries, or an empty list when parsing fails.</returns>
public static async Task<List<StoreLogEntry>> GetStoreLogEntriesAsync(HttpClient httpClient, int storeId, string fromDate, string toDate, string storeLogActionIds)
{
var responseBody = await GetStoreLogAsync(httpClient, storeId, fromDate, toDate, storeLogActionIds);
var opts = new JsonSerializerOptions
{
PropertyNameCaseInsensitive = true,
PropertyNamingPolicy = null
};
try
{
return JsonSerializer.Deserialize<List<StoreLogEntry>>(responseBody, opts) ?? [];
}
catch (JsonException ex)
{
Logger.Error(ex, "Failed to parse store log response.");
return [];
}
}
#endregion
#region Public Method PatchPickupAsync
/// <summary>