using Omika.Core.Contracts.Mobile.Sync;
using Omika.Core.Domain.Commands;
using Omika.Core.Services.Mobile;
using Omika.Data.Configuration;
using Omika.Data.Connection;
using Omika.Data.HfSql.Metadata;
using Omika.Data.Repositories.Batik;
namespace Omika.Tests.Repositories.Batik;
///
/// Tests unitaires de la création d'un compte rendu Batik
/// () centrés sur la colonne
/// CR_IDCollaborateur : aucun serveur HFSQL, aucun ODBC réel, aucun réseau.
/// Un fake enregistre le SQL et les paramètres, et
/// retourne des dictionnaires selon la table interrogée.
///
/// Objectifs :
///
/// la colonne porte l'identité du collaborateur AUTEUR du compte rendu, et
/// non plus systématiquement le collaborateur affecté à Planning_RDV ;
/// le PK numérique du jeton mobile est repris tel quel, et le GUID
/// synthétique réversible Batik est décodé (la table Collaborateur Batik
/// ne porte aucune colonne GUID) ;
/// à défaut d'auteur résolvable, le collaborateur affecté au rendez-vous
/// reste le repli historique : la colonne n'est jamais laissée vide.
///
///
public class BatikCompteRenduRepositoryTests
{
private const long RendezVousId = 42L;
private const long CollaborateurDuRendezVous = 7L;
[Fact]
public async Task CreateAsync_AuteurNumerique_RenseigneLAuteurEtNonLeCollaborateurDuRendezVous()
{
var connection = new FakeHfsqlConnection
{
PlanningRows = [PlanningRow()],
CompteRenduRows = [CompteRenduRow()]
};
var repository = new BatikCompteRenduRepository(connection);
await repository.CreateAsync("42", Command("9"));
ExecutedCommand insert = Insert(connection);
// 9 (auteur) et non 7 (collaborateur affecté à Planning_RDV).
Assert.Equal(9L, CrIdCollaborateur(insert));
}
[Fact]
public async Task CreateAsync_AuteurGuidSynthetique_DecodeLePkNumerique()
{
var connection = new FakeHfsqlConnection
{
PlanningRows = [PlanningRow()],
CompteRenduRows = [CompteRenduRow()]
};
var repository = new BatikCompteRenduRepository(connection);
// Identité publique Batik : GUID synthétique réversible dérivé du CO_PKID 55.
Guid auteurSynthetique = MobileEntityIdentityResolver.EncodeSyntheticIdentity(
SyncEntityTypes.Collaborateur, 55L);
await repository.CreateAsync("42", Command(auteurSynthetique.ToString("D")));
ExecutedCommand insert = Insert(connection);
Assert.Equal(55L, CrIdCollaborateur(insert));
}
[Fact]
public async Task CreateAsync_SansAuteur_RetombeSurLeCollaborateurDuRendezVous()
{
var connection = new FakeHfsqlConnection
{
PlanningRows = [PlanningRow()],
CompteRenduRows = [CompteRenduRow()]
};
var repository = new BatikCompteRenduRepository(connection);
await repository.CreateAsync("42", Command(collaborateurId: null));
ExecutedCommand insert = Insert(connection);
Assert.Equal(CollaborateurDuRendezVous, CrIdCollaborateur(insert));
}
[Fact]
public async Task CreateAsync_AuteurNonResolvable_RetombeSurLeCollaborateurDuRendezVous()
{
// GUID non canonique (ni PK numérique, ni GUID synthétique réversible) :
// la colonne est remplie avec le repli plutôt que laissée à 0.
var connection = new FakeHfsqlConnection
{
PlanningRows = [PlanningRow()],
CompteRenduRows = [CompteRenduRow()]
};
var repository = new BatikCompteRenduRepository(connection);
await repository.CreateAsync("42", Command(Guid.NewGuid().ToString("D")));
ExecutedCommand insert = Insert(connection);
Assert.Equal(CollaborateurDuRendezVous, CrIdCollaborateur(insert));
}
// =========================================================================
// Helpers
// =========================================================================
private static CompteRenduCreateCommand Command(string? collaborateurId)
=> new()
{
CollaborateurId = collaborateurId,
NoteCollaborateur = "Note du technicien"
};
private static Dictionary PlanningRow()
=> new()
{
["PL_PKID"] = RendezVousId,
["PL_IDIntervention"] = 12L,
["PL_IDCollaborateur"] = CollaborateurDuRendezVous,
["PL_IDGroupe"] = 0L
};
private static Dictionary CompteRenduRow()
=> new()
{
["CR_PKID"] = 1L,
["GUID"] = Guid.NewGuid().ToString("D")
};
private static ExecutedCommand Insert(FakeHfsqlConnection connection)
=> Assert.Single(connection.Writes.Where(write =>
write.Sql.Contains("INSERT INTO CompteRendu", StringComparison.OrdinalIgnoreCase)).ToList());
/// Valeur du paramètre de la colonne CR_IDCollaborateur.
private static object? CrIdCollaborateur(ExecutedCommand insert)
=> HfsqlInsertParameters.ValueFor(insert.Sql, insert.Parameters, "CR_IDCollaborateur");
private sealed record ExecutedCommand(string Sql, IReadOnlyList