Attempt to build a projection of arriving guests based on the events from the Projections Explained workshop.
Last active
June 28, 2016 21:38
-
-
Save marijn/3b1199047cd551c222b21a338e751c45 to your computer and use it in GitHub Desktop.
Attempt to build a projection of arriving guests based on the events from the Projections Explained workshop.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
const GuestBookedAppointment = "GuestBookedAppointment"; | |
const GuestRescheduledAppointment = "GuestRescheduledAppointment"; | |
const GuestSwappedAppointmentForFeelgoodPackage = "GuestSwappedAppointmentForFeelgoodPackage"; | |
const GuestCanceledAppointment = "GuestCanceledAppointment"; | |
const SubsidiaryCanceledAppointment = "SubsidiaryCanceledAppointment"; | |
class GuestsArriving { | |
constructor(day, subsidiary, arrivals) { | |
this.day = day; | |
this.subsidiary = subsidiary; | |
this.arrivals = arrivals; | |
} | |
equals(anotherGuestsArrivingModel) { | |
return anotherGuestsArrivingModel instanceof GuestsArriving | |
&& this.day == anotherGuestsArrivingModel.day | |
&& this.subsidiary == anotherGuestsArrivingModel.subsidiary | |
&& this.arrivals.equals(anotherGuestsArrivingModel.arrivals); | |
} | |
withAdditionalArrival(scheduledArrival) { | |
this.arrivals.arrivals.push(scheduledArrival); | |
return this; | |
} | |
} | |
class Arrivals { | |
constructor(arrivals) { | |
this.arrivals = arrivals; | |
} | |
equals(anotherListOfArrivals) { | |
return anotherListOfArrivals instanceof Arrivals | |
&& anotherListOfArrivals.arrivals.length == this.arrivals.length | |
&& this.containsSameArrivalsAs(anotherListOfArrivals); | |
} | |
containsSameArrivalsAs(anotherListOfArrivals) { | |
let containsSameArrivals = true; | |
for (let i = 0, numberOfArrivals = this.arrivals.length; i < numberOfArrivals && containsSameArrivals; i++) { | |
containsSameArrivals = this.arrivals[i].equals(anotherListOfArrivals.arrivals[i]); | |
} | |
return containsSameArrivals; | |
} | |
} | |
class ScheduledArrival { | |
constructor(guest, expectedTimeOfArrival, hasBeenCanceledBySubsidiary) { | |
this.guest = guest; | |
this.expectedTimeOfArrival = expectedTimeOfArrival; | |
this.hasBeenCanceledBySubsidiary = hasBeenCanceledBySubsidiary; | |
} | |
equals(anotherArrival) { | |
return anotherArrival instanceof ScheduledArrival | |
&& this.guest == anotherArrival.guest | |
&& this.expectedTimeOfArrival == anotherArrival.expectedTimeOfArrival | |
&& this.hasBeenCanceledBySubsidiary == anotherArrival.hasBeenCanceledBySubsidiary; | |
} | |
} | |
class GuestsArrivingProjector { | |
static generateKey(day, idOfSubsidiary) { | |
return `${day}#${idOfSubsidiary}`; | |
} | |
constructor() { | |
this.records = {}; | |
} | |
projectAll(events) { | |
events.forEach((event) => { | |
switch (event.message) { | |
case GuestBookedAppointment: | |
this.whenGuestBookedAppointment(event); | |
break; | |
default: | |
// intentionally ignore | |
} | |
}); | |
} | |
totalCount() { | |
return Object.keys(this.records).length; | |
} | |
ofDayAndSubsidiary(day, idOfSubsidiary) { | |
var key = GuestsArrivingProjector.generateKey(day, idOfSubsidiary); | |
// TODO: SorryNoRecordCouldBeFound | |
return this.records[key]; | |
} | |
whenGuestBookedAppointment(anEvent) { | |
let key = GuestsArrivingProjector.generateKey(anEvent.dateOfAppointment, anEvent.subsidiaryId); | |
let record = this.ofDayAndSubsidiary(anEvent.dateOfAppointment, anEvent.subsidiaryId); | |
if (record) { | |
this.records[key] = record.withAdditionalArrival(new ScheduledArrival(anEvent.guestId, anEvent.timeOfAppointment, false)); | |
} else { | |
this.records[key] = new GuestsArriving( | |
anEvent.dateOfAppointment, | |
anEvent.subsidiaryId, | |
new Arrivals([new ScheduledArrival(anEvent.guestId, anEvent.timeOfAppointment, false)]) | |
); | |
} | |
return this.records[key]; | |
} | |
} | |
function testEqualityOfGuestsArriving () { | |
assertThat( | |
new GuestsArriving('2016-12-06', 'bonaficio', new Arrivals([])).equals(new GuestsArriving('2016-12-06', 'bonaficio', new Arrivals([]))) | |
); | |
} | |
function testEqualityOfArrivals () { | |
assertThat( | |
new Arrivals([]).equals(new Arrivals([])) | |
); | |
} | |
function testEqualityOfScheduledArrival () { | |
assertThat( | |
new ScheduledArrival('Arne', '12:15', false).equals(new ScheduledArrival('Arne', '12:15', false)) | |
); | |
} | |
function testProjectionOfGuestBookedAppointment() { | |
let projector = new GuestsArrivingProjector(); | |
let given = [ | |
{ | |
message: GuestBookedAppointment, | |
appointmentId: 123, | |
guestId: 456, | |
dateOfAppointment: "2016-12-06", | |
timeOfAppointment: "20:30", | |
feelgoodPackageId: 789, | |
subsidiaryId: 1 | |
} | |
]; | |
projector.projectAll(given); | |
assertThat(projector.totalCount() == 1); | |
assertThat(projector.ofDayAndSubsidiary('2016-12-06', 1).equals(new GuestsArriving("2016-12-06", 1, new Arrivals([new ScheduledArrival(456, '20:30', false)])))); | |
let additionalGiven = [ | |
{ | |
message: GuestBookedAppointment, | |
appointmentId: 123123, | |
guestId: 456456, | |
dateOfAppointment: "2016-12-06", | |
timeOfAppointment: "18:30", | |
feelgoodPackageId: 789789, | |
subsidiaryId: 1 | |
} | |
]; | |
projector.projectAll(additionalGiven); | |
assertThat(projector.totalCount() == 1); | |
assertThat(projector.ofDayAndSubsidiary('2016-12-06', 1).equals(new GuestsArriving("2016-12-06", 1, new Arrivals([new ScheduledArrival(456, '20:30', false), new ScheduledArrival(456456, '18:30', false)])))); | |
} | |
function testAll() { | |
testEqualityOfGuestsArriving(); | |
testEqualityOfArrivals(); | |
testEqualityOfScheduledArrival(); | |
testProjectionOfGuestBookedAppointment(); | |
} | |
function assertThat(aCondition) { | |
return aCondition | |
? console.log(aCondition) | |
: console.error(aCondition); | |
} | |
testAll(); |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment