feat StayExport - Added ExportDetails for StayExports

Store a new field ('ExportDetails') with export details. This is a JSON field in DB that can store information about the export depending on the format provider used.

Changes:
- Updated models and created required migrations.
- Show field in StayExport list.
This commit is contained in:
2026-09-08 19:58:47 +02:00
parent 7b8020879b
commit 9ec87d56da
16 changed files with 352 additions and 16 deletions
@@ -1,4 +1,5 @@
using System.Diagnostics;
using System.Text.Json;
using System.Xml.Serialization;
using FluentValidation;
using Microsoft.Extensions.Options;
@@ -17,6 +18,9 @@ public class StayExportProviderSpainParteViajeros(
{
private const string fileExtension = "xml";
private const string ExportDetailsResult_Error = "Error";
private const string ExportDetailsResult_Ok = "Ok";
private const string PersonRole = "VI";
private const string PersonRelation = "OT";
@@ -31,32 +35,35 @@ public class StayExportProviderSpainParteViajeros(
private readonly StayExportSpainParteViajerosConfig config = configOptions.Value;
public StayExportFormat GetFormat() => StayExportFormat.SpainParteViajeros;
public string GetFilename(DateTime exportTime)
=> $"{Enum.GetName(GetFormat())}_{exportTime.ToFileTimeUtc()}.{fileExtension}";
public async Task<StayExportFileResult> ExportDataAsync(IEnumerable<StayEntryDTO> stayList, Stream dataStream)
public async Task<(StayExportFileResult fileResult, string? exportDetails)> ExportDataAsync(IEnumerable<StayEntryDTO> stayList, Stream dataStream)
{
if (string.IsNullOrEmpty(config.CodigoEstablecimiento))
{
logger.LogError("StayExportProviderSpainParteViajeros - Config error: CodigoEstablecimiento is not configured!");
return StayExportFileResult.ExportError;
return (fileResult: StayExportFileResult.ExportError, exportDetails: null);
}
if (!stayList.Any())
{
return StayExportFileResult.NoData;
return (fileResult: StayExportFileResult.NoData, exportDetails: null);
}
List<StayExportDetails> stayExportDetails = [];
ComunicacionValidator comunicacionValidator = new();
List<Comunicacion> comunicacionsList = [];
foreach (StayEntryDTO stay in stayList)
{
(Comunicacion? comunicacion, string code) = await GetComunicacionFromStay(stay);
(Comunicacion? comunicacion, string errorMsg) = await GetComunicacionFromStay(stay);
if (comunicacion == null)
{
logger.LogWarning("StayExportProviderSpainParteViajeros - Stay (ID: {id}) can't be exported: Code: {code}", stay.Id, code);
logger.LogWarning("StayExportProviderSpainParteViajeros - Stay (ID: {id}) can't be exported: Error: {code}", stay.Id, errorMsg);
stayExportDetails.Add(new(StayId: stay.Id ?? -1, ExportResult: ExportDetailsResult_Error, Details: errorMsg));
continue;
}
@@ -64,11 +71,13 @@ public class StayExportProviderSpainParteViajeros(
if (!errors.IsValid)
{
logger.LogWarning("StayExportProviderSpainParteViajeros - Stay (ID: {id}) is invalid: Errors: {errors}", stay.Id, errors.Errors);
stayExportDetails.Add(new(StayId: stay.Id ?? -1, ExportResult: ExportDetailsResult_Error, Details: errors.ToString()));
continue;
}
comunicacionsList.Add(comunicacion);
logger.LogInformation("StayExportProviderSpainParteViajeros - Stay (ID: {id}) Exported OK", stay.Id);
stayExportDetails.Add(new(StayId: stay.Id ?? -1, ExportResult: ExportDetailsResult_Ok, Details: null));
}
Peticion peticion = new()
@@ -83,12 +92,13 @@ public class StayExportProviderSpainParteViajeros(
XmlSerializer serializer = new(typeof(Peticion));
serializer.Serialize(dataStream, peticion);
return StayExportFileResult.OK;
string details = JsonSerializer.Serialize(stayExportDetails);
return (fileResult: StayExportFileResult.OK, exportDetails: details);
}
#region Internal Methods
private async Task<(Comunicacion? comunicacion, string code)> GetComunicacionFromStay(StayEntryDTO stay)
private async Task<(Comunicacion? comunicacion, string errorMsg)> GetComunicacionFromStay(StayEntryDTO stay)
{
Debug.Assert(stay.Id != null
&& stay.DateIn != null
@@ -136,7 +146,7 @@ public class StayExportProviderSpainParteViajeros(
{
return (
comunicacion: null,
code: "NoCodigoMunicipio"
errorMsg: "Can't get codigo municio"
);
}
}
@@ -167,7 +177,7 @@ public class StayExportProviderSpainParteViajeros(
contrato = contrato,
persona = personasList
},
code: "OK");
errorMsg: "OK");
}
private static string? GetTipoDocumentoFromGuest(GuestDocumentDTO doc)
@@ -309,6 +319,8 @@ public class StayExportProviderSpainParteViajeros(
#region Export Data Classes
private record StayExportDetails(long StayId, string ExportResult, string? Details);
[XmlRoot(ElementName = "peticion", Namespace = XmlNamespace_Peticion)]
public class Peticion
{