manager-service/ManagerService/Services/AgendaSyncService.cs

135 lines
5.4 KiB
C#

using Manager.DTOs;
using ManagerService.Data;
using ManagerService.Data.SubSection;
using ManagerService.DTOs;
using Microsoft.EntityFrameworkCore;
using Microsoft.Extensions.DependencyInjection;
using Microsoft.Extensions.Logging;
using Newtonsoft.Json;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Net.Http;
using System.Threading.Tasks;
namespace ManagerService.Services
{
public class AgendaSyncService
{
private readonly ILogger<AgendaSyncService> _logger;
private readonly IServiceScopeFactory _scopeFactory;
private readonly IHttpClientFactory _httpClientFactory;
public AgendaSyncService(ILogger<AgendaSyncService> logger, IServiceScopeFactory scopeFactory, IHttpClientFactory httpClientFactory)
{
_logger = logger;
_scopeFactory = scopeFactory;
_httpClientFactory = httpClientFactory;
}
public async Task SyncAllAsync()
{
using var scope = _scopeFactory.CreateScope();
var db = scope.ServiceProvider.GetRequiredService<MyInfoMateDbContext>();
var sections = db.Sections.OfType<SectionAgenda>()
.Where(sa => sa.IsOnlineAgenda && sa.AgendaResourceIds != null && sa.AgendaResourceIds.Count > 0)
.Select(sa => sa.Id)
.ToList();
foreach (var id in sections)
{
try { await SyncSectionAsync(id); }
catch (Exception ex) { _logger.LogError(ex, "Error syncing agenda section {Id}", id); }
}
}
public async Task SyncSectionAsync(string sectionAgendaId)
{
using var scope = _scopeFactory.CreateScope();
var db = scope.ServiceProvider.GetRequiredService<MyInfoMateDbContext>();
var section = db.Sections.OfType<SectionAgenda>()
.Include(sa => sa.EventAgendas)
.FirstOrDefault(sa => sa.Id == sectionAgendaId);
if (section == null || !section.IsOnlineAgenda || section.AgendaResourceIds == null)
return;
var http = _httpClientFactory.CreateClient();
foreach (var resourceRef in section.AgendaResourceIds)
{
if (string.IsNullOrEmpty(resourceRef.value) || string.IsNullOrEmpty(resourceRef.language))
continue;
var resource = db.Resources.FirstOrDefault(r => r.Id == resourceRef.value);
if (resource == null || string.IsNullOrEmpty(resource.Url))
continue;
List<RemoteEventAgendaDTO> remoteEvents;
try
{
var json = await http.GetStringAsync(resource.Url);
remoteEvents = JsonConvert.DeserializeObject<List<RemoteEventAgendaDTO>>(json, RemoteAgendaJsonSettings.Lenient) ?? new();
}
catch (Exception ex)
{
_logger.LogWarning(ex, "Failed to fetch agenda JSON for section {Id} language {Lang}", sectionAgendaId, resourceRef.language);
continue;
}
foreach (var remote in remoteEvents)
{
var dateFrom = remote.GetDateFrom();
// Match on DateFrom (date part only), restricted to IsSynced events
var existing = section.EventAgendas.FirstOrDefault(ea =>
ea.IsSynced &&
ea.DateFrom.HasValue &&
dateFrom.HasValue &&
ea.DateFrom.Value.Date == dateFrom.Value.Date);
if (existing == null)
{
existing = new EventAgenda
{
Label = new List<TranslationDTO>(),
Description = new List<TranslationDTO>(),
SectionAgendaId = sectionAgendaId,
IsSynced = true,
};
section.EventAgendas.Add(existing);
db.EventAgendas.Add(existing);
}
// Update / set translation for this language
SetTranslation(existing.Label, resourceRef.language, remote.name);
SetTranslation(existing.Description, resourceRef.language, remote.description);
// Non-translated fields (last language wins, acceptable)
existing.DateFrom = dateFrom;
existing.DateTo = remote.GetDateTo();
existing.Phone = remote.phone;
existing.Email = remote.email;
existing.Website = remote.website;
existing.IdVideoYoutube = remote.id_video_youtube;
existing.IsSynced = true;
}
}
db.SaveChanges();
_logger.LogInformation("Synced agenda section {Id}", sectionAgendaId);
}
private static void SetTranslation(List<TranslationDTO> list, string language, string? value)
{
var existing = list.FirstOrDefault(t => t.language == language);
if (existing != null)
existing.value = value ?? "";
else
list.Add(new TranslationDTO { language = language, value = value ?? "" });
}
}
}