302 lines
12 KiB
C#
302 lines
12 KiB
C#
using Omika.Core.Compatibility;
|
|
using Omika.Core.Domain.Entities.Interventions;
|
|
using Omika.Data.Mapping.Common;
|
|
using OmikaModels = Omika.Data.HfSql.Models.Omika;
|
|
using OmikaMappers = Omika.Data.Mapping.Omika;
|
|
|
|
namespace Omika.Tests.Mapping;
|
|
|
|
/// <summary>
|
|
/// Tests unitaires du mapper Omika → canonique des interventions.
|
|
/// Aucune base réelle, aucun HFSQL : uniquement des objets en mémoire.
|
|
///
|
|
/// Le mapper ne renseigne pas <c>SourceReference</c> sur l'entité canonique
|
|
/// (la référence source est construite en interne mais non affectée) ; ces
|
|
/// tests se concentrent donc sur les propriétés canoniques réellement mappées.
|
|
/// </summary>
|
|
public class OmikaInterventionMapperTests
|
|
{
|
|
// ---- 1. Intervention Omika minimale -------------------------------------------
|
|
|
|
[Fact]
|
|
public void InterventionOmika_Minimal_MapsWithoutExceptionAndKeepsNoFabricatedValue()
|
|
{
|
|
var row = new OmikaModels.InterventionRow { INPKID = 1 };
|
|
|
|
CanonicalMappingResult<Intervention> result = OmikaMappers.OmikaInterventionMapper.Map(row);
|
|
|
|
Assert.Equal(DatabaseSchemaVersion.Omika, result.SourceVersion);
|
|
Assert.NotNull(result.Value);
|
|
Assert.Null(result.Value.Titre);
|
|
Assert.Null(result.Value.Reference);
|
|
Assert.Null(result.Value.Type);
|
|
Assert.Null(result.Value.Etat);
|
|
Assert.False(result.Value.EstArchive);
|
|
Assert.Empty(result.Warnings);
|
|
}
|
|
|
|
// ---- 2. Intervention Omika complète -------------------------------------------
|
|
|
|
[Fact]
|
|
public void InterventionOmika_Full_MapsAllCanonicalProperties()
|
|
{
|
|
var row = new OmikaModels.InterventionRow
|
|
{
|
|
INPKID = 42,
|
|
INTitre = "Réparation chaudière",
|
|
INRefInterne = "INT-042",
|
|
INDescription = "Remplacement de la chaudière",
|
|
INCleType = "TYP-MAINT",
|
|
INCleEtat = "STA-ENCOURS",
|
|
INDateIntervention = new DateOnly(2026, 3, 15),
|
|
Archive = true,
|
|
INIDImport = "IMP-O-42",
|
|
GUID = "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa"
|
|
};
|
|
|
|
var referenceRows = new Dictionary<string, OmikaModels.ParametreMetierRow>
|
|
{
|
|
["TYP-MAINT"] = new() { PAPKID = 2, PACLE = "TYP-MAINT", PALibelle = "Maintenance" },
|
|
["STA-ENCOURS"] = new() { PAPKID = 3, PACLE = "STA-ENCOURS", PALibelle = "En cours" }
|
|
};
|
|
|
|
CanonicalMappingResult<Intervention> result = OmikaMappers.OmikaInterventionMapper.Map(row, referenceRows);
|
|
|
|
Intervention intervention = result.Value;
|
|
Assert.Equal("Réparation chaudière", intervention.Titre);
|
|
Assert.Equal("INT-042", intervention.Reference);
|
|
Assert.Equal("Remplacement de la chaudière", intervention.Description);
|
|
Assert.Equal("Maintenance", intervention.Type!.Label);
|
|
Assert.Equal("TYP-MAINT", intervention.Type!.Key);
|
|
Assert.Equal("En cours", intervention.Etat!.Label);
|
|
Assert.Equal("STA-ENCOURS", intervention.Etat!.Key);
|
|
Assert.Equal(new DateTime(2026, 3, 15), intervention.DatePrevueDebut);
|
|
Assert.True(intervention.EstArchive);
|
|
}
|
|
|
|
// ---- 3. GUID ------------------------------------------------------------------
|
|
|
|
[Fact]
|
|
public void InterventionOmika_InvalidGuid_ProducesWarning()
|
|
{
|
|
var row = new OmikaModels.InterventionRow { INPKID = 42, GUID = "not-a-valid-guid" };
|
|
|
|
CanonicalMappingResult<Intervention> result = OmikaMappers.OmikaInterventionMapper.Map(row);
|
|
|
|
Assert.Contains(result.Warnings, w => w.Contains(MappingWarningCodes.InvalidPhysicalGuid, StringComparison.Ordinal));
|
|
}
|
|
|
|
[Fact]
|
|
public void InterventionOmika_EmptyGuid_NoWarning()
|
|
{
|
|
var row = new OmikaModels.InterventionRow { INPKID = 42, GUID = "" };
|
|
|
|
CanonicalMappingResult<Intervention> result = OmikaMappers.OmikaInterventionMapper.Map(row);
|
|
|
|
Assert.Empty(result.Warnings);
|
|
}
|
|
|
|
// ---- 4. Type et état (clés métier) --------------------------------------------
|
|
|
|
[Fact]
|
|
public void InterventionOmika_Type_IsResolvedFromCleType()
|
|
{
|
|
var row = new OmikaModels.InterventionRow { INPKID = 5, INCleType = "TYP-URG" };
|
|
|
|
var referenceRows = new Dictionary<string, OmikaModels.ParametreMetierRow>
|
|
{
|
|
["TYP-URG"] = new() { PAPKID = 7, PACLE = "TYP-URG", PALibelle = "Urgence" }
|
|
};
|
|
|
|
CanonicalMappingResult<Intervention> result = OmikaMappers.OmikaInterventionMapper.Map(row, referenceRows);
|
|
|
|
Assert.NotNull(result.Value.Type);
|
|
Assert.Equal("Urgence", result.Value.Type!.Label);
|
|
Assert.Equal("TYP-URG", result.Value.Type!.Key);
|
|
Assert.Empty(result.Warnings);
|
|
}
|
|
|
|
[Fact]
|
|
public void InterventionOmika_UnresolvedType_KeepsKeyAndWarns()
|
|
{
|
|
var row = new OmikaModels.InterventionRow { INPKID = 6, INCleType = "TYP-INCONNU" };
|
|
|
|
CanonicalMappingResult<Intervention> result = OmikaMappers.OmikaInterventionMapper.Map(row);
|
|
|
|
Assert.NotNull(result.Value.Type);
|
|
Assert.Equal("TYP-INCONNU", result.Value.Type!.Key);
|
|
Assert.Equal(string.Empty, result.Value.Type!.Label);
|
|
Assert.Contains(result.Warnings, w => w.Contains("IN_CleType", StringComparison.Ordinal));
|
|
}
|
|
|
|
[Fact]
|
|
public void InterventionOmika_NoTypeKey_ProducesNoReference()
|
|
{
|
|
var row = new OmikaModels.InterventionRow { INPKID = 8 };
|
|
|
|
CanonicalMappingResult<Intervention> result = OmikaMappers.OmikaInterventionMapper.Map(row);
|
|
|
|
Assert.Null(result.Value.Type);
|
|
Assert.Empty(result.Warnings);
|
|
}
|
|
|
|
[Fact]
|
|
public void InterventionOmika_UnresolvedEtat_KeepsKeyAndWarns()
|
|
{
|
|
var row = new OmikaModels.InterventionRow { INPKID = 9, INCleEtat = "STA-INCONNU" };
|
|
|
|
CanonicalMappingResult<Intervention> result = OmikaMappers.OmikaInterventionMapper.Map(row);
|
|
|
|
Assert.NotNull(result.Value.Etat);
|
|
Assert.Equal("STA-INCONNU", result.Value.Etat!.Key);
|
|
Assert.Contains(result.Warnings, w => w.Contains("IN_CleEtat", StringComparison.Ordinal));
|
|
}
|
|
|
|
// ---- 5. Champs ignorés --------------------------------------------------------
|
|
|
|
[Fact]
|
|
public void InterventionOmika_FieldsWithoutCanonicalEquivalent_AreReportedAsIgnored()
|
|
{
|
|
var row = new OmikaModels.InterventionRow
|
|
{
|
|
INPKID = 15,
|
|
INIDClient = 1,
|
|
INIDLieu = 2,
|
|
INIDDossier = 3,
|
|
INIDSuiviPar = 4,
|
|
INIDDemandeur = 5,
|
|
INIDSociete = 6,
|
|
INAttestationTVAPresente = true,
|
|
INNoteInterne = "note",
|
|
INRefExterne = "EXT-1",
|
|
INDureePrevue = 2.5f,
|
|
INNumDevis = "DEV-1",
|
|
INDateDevis = new DateOnly(2026, 1, 1),
|
|
INNumFacture = "FAC-1",
|
|
INDateFacture = new DateOnly(2026, 2, 1),
|
|
INNumIntervention = "N-1",
|
|
ModifDate = new DateTime(2024, 1, 1),
|
|
CreationDate = new DateTime(2023, 1, 1),
|
|
DateArchivage = new DateTime(2024, 6, 1)
|
|
};
|
|
|
|
CanonicalMappingResult<Intervention> result = OmikaMappers.OmikaInterventionMapper.Map(row);
|
|
|
|
Assert.Contains(result.IgnoredFields, f => f == "IN_IDClient");
|
|
Assert.Contains(result.IgnoredFields, f => f == "IN_IDLieu");
|
|
Assert.Contains(result.IgnoredFields, f => f == "IN_IDDossier");
|
|
Assert.Contains(result.IgnoredFields, f => f == "IN_IDSuiviPar");
|
|
Assert.Contains(result.IgnoredFields, f => f == "IN_IDDemandeur");
|
|
Assert.Contains(result.IgnoredFields, f => f == "IN_IDSociete");
|
|
Assert.Contains(result.IgnoredFields, f => f == "IN_AttestationTVAPresente");
|
|
Assert.Contains(result.IgnoredFields, f => f == "IN_NoteInterne");
|
|
Assert.Contains(result.IgnoredFields, f => f == "IN_DureePrevue");
|
|
Assert.Contains(result.IgnoredFields, f => f == "IN_DateDevis");
|
|
Assert.Contains(result.IgnoredFields, f => f == "IN_DateFacture");
|
|
Assert.Equal(new DateTime(2024, 1, 1), result.Value.DateModification);
|
|
Assert.Contains(result.IgnoredFields, f => f == "CreationDate");
|
|
Assert.Contains(result.IgnoredFields, f => f == "DateArchivage");
|
|
|
|
// Champs désormais dotés d'un équivalent canonique : ils ne sont plus
|
|
// ignorés, ils sont mappés dans l'entité Intervention.
|
|
Assert.Equal("EXT-1", result.Value.ReferenceExterne);
|
|
Assert.Equal("DEV-1", result.Value.NumeroDevis);
|
|
Assert.Equal("N-1", result.Value.NumeroIntervention);
|
|
Assert.Equal("FAC-1", result.Value.NumeroFacture);
|
|
}
|
|
|
|
// ---- 6. Aucune exception sur les chaînes vides --------------------------------
|
|
|
|
[Fact]
|
|
public void InterventionOmika_EmptyOrNullStrings_NeverThrow()
|
|
{
|
|
var row = new OmikaModels.InterventionRow
|
|
{
|
|
INTitre = "",
|
|
INRefInterne = " ",
|
|
INDescription = "",
|
|
INNoteInterne = " ",
|
|
INRefExterne = "",
|
|
INIDImport = " "
|
|
};
|
|
|
|
CanonicalMappingResult<Intervention> result = OmikaMappers.OmikaInterventionMapper.Map(row);
|
|
|
|
Assert.NotNull(result.Value);
|
|
Assert.Null(result.Value.Titre);
|
|
Assert.Null(result.Value.Reference);
|
|
Assert.Null(result.Value.Description);
|
|
Assert.Empty(result.Warnings);
|
|
}
|
|
|
|
[Fact]
|
|
public void InterventionOmika_DefaultRow_NeverThrows()
|
|
{
|
|
var row = new OmikaModels.InterventionRow();
|
|
|
|
CanonicalMappingResult<Intervention> result = OmikaMappers.OmikaInterventionMapper.Map(row);
|
|
|
|
Assert.NotNull(result.Value);
|
|
Assert.False(result.Value.EstArchive);
|
|
}
|
|
|
|
// ---- 7. Absence de noms physiques HFSQL dans le domaine canonique -------------
|
|
|
|
[Fact]
|
|
public void InterventionOmika_CanonicalDomain_DoesNotExposeHfSqlNames()
|
|
{
|
|
var row = new OmikaModels.InterventionRow
|
|
{
|
|
INPKID = 40,
|
|
INTitre = "Titre",
|
|
INRefInterne = "INT-040",
|
|
INDescription = "desc",
|
|
INCleType = "TYP-MAINT",
|
|
INCleEtat = "STA-ENCOURS",
|
|
INDateIntervention = new DateOnly(2026, 1, 1),
|
|
Archive = false,
|
|
INIDImport = "IMP-40",
|
|
INIDClient = 1,
|
|
INIDLieu = 2,
|
|
INIDDossier = 3,
|
|
INIDSuiviPar = 4,
|
|
INIDDemandeur = 5,
|
|
INIDSociete = 6,
|
|
INAttestationTVAPresente = true,
|
|
INNoteInterne = "note",
|
|
INRefExterne = "EXT",
|
|
INDureePrevue = 1f,
|
|
INNumDevis = "DEV",
|
|
INNumFacture = "FAC",
|
|
INNumIntervention = "N",
|
|
GUID = "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa"
|
|
};
|
|
|
|
var referenceRows = new Dictionary<string, OmikaModels.ParametreMetierRow>
|
|
{
|
|
["TYP-MAINT"] = new() { PAPKID = 2, PACLE = "TYP-MAINT", PALibelle = "Maintenance" },
|
|
["STA-ENCOURS"] = new() { PAPKID = 3, PACLE = "STA-ENCOURS", PALibelle = "En cours" }
|
|
};
|
|
|
|
CanonicalMappingResult<Intervention> result = OmikaMappers.OmikaInterventionMapper.Map(row, referenceRows);
|
|
Intervention intervention = result.Value;
|
|
|
|
string[] forbidden =
|
|
[
|
|
"IN_", "PA_", "PKID", "HfSql", "HFSQL"
|
|
];
|
|
|
|
AssertHasNoPhysicalNames(intervention, forbidden);
|
|
}
|
|
|
|
// ---- Helper -------------------------------------------------------------------
|
|
|
|
private static void AssertHasNoPhysicalNames(object value, string[] forbidden)
|
|
{
|
|
foreach (var property in value.GetType().GetProperties())
|
|
{
|
|
Assert.DoesNotContain(forbidden, f => property.Name.Contains(f, StringComparison.Ordinal));
|
|
}
|
|
}
|
|
}
|