J'ai réorganisé notre moteur de disponibilité il y a quelques mois afin de faire passer notre logique d'une base de données à un micro service. A ce moment-là, la logique métier était assez simple:Comment déterminer la disponibilité combinée des salles DDD
Une ressource (salle de réunion, un bureau, un bureau vide, équipement) est disponible sur un laps de temps donné seulement si elle est pas déjà réservé (ex: pas d'autre la réservation en utilisant la même ressource)
Lorsqu'une ressource est pas disponible, les plus proches délais disponibles doivent être calculés
Pour couvrir ces besoins, je construit le petit morceau de code ci-dessous:
public class Schedule : IAggregateRoot
{
public int CityId { get; }
public int BuildingId { get; }
public int CentreId { get; }
public int ResourceId { get; }
public ICollection<Booking> Bookings { get; }
public Schedule(int cityId, int buildingId, int centreId, int resourceId, IEnumerable<Booking> bookings)
{
CityId = cityId;
BuildingId = buildingId;
CentreId = centreId;
ResourceId = resourceId;
Bookings = new List<Booking>(bookings);
}
public bool IsTimeSlotFree(DateTimeOffset startDate, DateTimeOffset endDate)
=> Bookings.Any(/* Predicate */);
public IEnumerable<Availability> GetFreeTimeSlots(
DateTimeOffset startDate,
DateTimeOffset endDate,
TimeSpan duration)
{
var nbSlots = Math.Floor((endDate - startDate)/duration);
for(int i=0; i<nbSlots; i++) {
/* yield return availability */
}
}
}
public class Availability : ValueObject
{
public DateTimeOffset StartDate { get; set; }
public DateTimeOffset EndDate { get; set; }
public int ResourceId { get; set; }
public bool IsAvailable { get; set; }
}
public class Resource : Entity
{
public string Code { get; set; }
// Required for EF Core
protected Resource() { }
}
public class Booking : Entity
{
public DateTimeOffset StartDate { get; set; }
public DateTimeOffset EndDate { get; set; }
public string Status { get; set; }
public int ResourceId { get; set; }
// Required for EF Core
protected Booking() { }
}
Il y a quelques semaines, on m'a demandé de gérer des salles combinées (deux salles plus petites peuvent être fusionnées en une salle plus grande). Dans ce scénario une salle combinée est disponible SEULEMENT ses sous-salles et elle-même sont disponibles. En d'autres termes, j'ai besoin de vérifier plusieurs horaires pour déterminer la disponibilité et, malheureusement, mon niveau actuel d'abstraction ne le permet pas (un horaire, une salle).
La seule façon que j'ai trouvé est de récupérer une ressource et ses enfants (= subrooms) et ensuite créer un calendrier contenant un dictionnaire de ResourceId et des réservations.
public class Resource : Entity
{
public string Code { get; set; }
public Resource Parent { get; set; }
public ICollection<Resource> Children { get; set; }
// Required for EF Core
protected Resource() { }
}
public class Schedule : IAggregateRoot
{
public int CityId { get; }
public int BuildingId { get; }
public int CentreId { get; }
public int ResourceId { get; }
public IDictionnary<int, ICollection<Bookings>> Bookings
(...)
}
Je ne trouve pas cette solution vraiment élégante. Pour moi, une meilleure solution serait de récupérer les horaires et de les combiner afin de déterminer la disponibilité réelle. J'ai essayé plusieurs solutions mais j'ai fini par écrire du code spaghetti.
Avez-vous des idées sur la façon dont je pourrais re-concevoir mes agrégats pour gérer correctement ce nouveau concept?
Merci, Seb
Y a-t-il des possibilités de sous-salles limitées connues à l'avance ou peut-on combiner deux pièces en une plus grande? – guillaume31
Oui, ils sont connus à l'avance. Je sais quelles pièces peuvent être combinées. En fait, je stocke cette information dans un db :) – Seb