public Result <Nothing, Error> RecordContact(RecordContact.Command command, ApplicationUser recordingUser, Instant now) { Guard.Against.Null(command, nameof(command)); Guard.Against.Null(recordingUser, nameof(recordingUser)); Guard.Against.Default(now, nameof(now)); ValidateIdMatchOrThrow(command.SchoolId); return(Validate(new RecordContact.Validator(), command) .Ensure( _ => this.IsNew == false, new Error.ResourceNotFound(Messages.School_not_found)) .Ensure( _ => now > command.ContactTimestamp, new Error.DomainError(RecordContact_Messages.Contact_timestamp_cannot_be_later_than_current_timestamp)) .Tap( _ => Emit(new ContactOccured( recordingUserId: recordingUser.Id, contactTimestamp: command.ContactTimestamp, communicationChannel: command.CommunicationChannel, emailAddress: command.CommunicationChannel.IsEmail ? command.EmailAddress : null, phoneNumber: command.CommunicationChannel.IsPhone ? command.PhoneNumber : null, contactPersonName: command.ContactPersonName, content: command.Content, additionalNotes: command.AdditionalNotes)) )); }
public void CommandMustBeExecutedOnAggregateWithMatchingEnrollmentId() { var enrollment = new EnrollmentAggregate(EnrollmentAggregate.EnrollmentId.New); var recordingUser = new ApplicationUser() { Id = Guid.NewGuid() }; var command = new RecordContact.Command() { EnrollmentId = EnrollmentAggregate.EnrollmentId.New.GetGuid(), CommunicationChannel = CommunicationChannel.OutgoingEmail, Content = "ala ma kota", AdditionalNotes = "notatka testowa" }; Assert.Throws <AggregateMismatchException>(() => enrollment.RecordContact( new RecordContact.Command() { EnrollmentId = EnrollmentAggregate.EnrollmentId.New.GetGuid(), CommunicationChannel = CommunicationChannel.OutgoingEmail, Content = "ala ma kota", AdditionalNotes = "notatka testowa" }, recordingUser)); }
public async Task <Result <Nothing, Error> > Handle(RecordContact.Command request, CancellationToken cancellationToken) { var user = await _userAccessor.GetUser(); var result = await _aggregateStore.Update <SchoolAggregate, SchoolId, Result <Nothing, Error> >( SchoolId.With(request.SchoolId), CommandId.New, (aggregate) => aggregate.RecordContact(request, user, _clock.GetCurrentInstant()), cancellationToken); return(result.Unwrap()); }
public async Task <Result <Nothing, Error> > Handle(RecordContact.Command request, CancellationToken cancellationToken) { var user = await _userAccessor.GetUser(); var result = await _aggregateStore.Update <EnrollmentAggregate, EnrollmentId, Result <Nothing, Error> >( EnrollmentId.With(request.EnrollmentId), CommandId.New, (aggregate) => aggregate.RecordContact(request, user), cancellationToken); return(result.Unwrap()); }
public void After_registering_contact__aggregate_contains_ContactOccured_event() { var school = new SchoolAggregate(SchoolId.New); var registeringUser = new ApplicationUser() { Id = Guid.NewGuid() }; school.RegisterSchool( NodaTime.SystemClock.Instance.GetCurrentInstant() - NodaTime.Duration.FromDays(2), new RegisterSchool.Command() { Name = "I Liceum Ogólnokształcące", City = "Gdańsk", Address = "Wały Piastowskie 6", ContactData = new[] { new ContactData() { Name = "sekretariat", EmailAddress = EmailAddress.Parse("*****@*****.**"), PhoneNumber = PhoneNumber.Parse("58 301-67-34") }, } }, registeringUser); var command = new RecordContact.Command() { SchoolId = school.Id.GetGuid(), ContactTimestamp = NodaTime.SystemClock.Instance.GetCurrentInstant() - NodaTime.Duration.FromDays(1), CommunicationChannel = CommunicationChannelType.OutgoingEmail, EmailAddress = EmailAddress.Parse("*****@*****.**"), PhoneNumber = null, ContactPersonName = "Andrzej Strzelba", Content = "treść", AdditionalNotes = "notatka" }; var result = school.RecordContact(command, registeringUser, NodaTime.SystemClock.Instance.GetCurrentInstant()); Assert.True(result.IsSuccess); var uncommittedEvent = Assert.Single(school.UncommittedEvents, @event => @event.AggregateEvent is ContactOccured); var @event = Assert.IsType <ContactOccured>(uncommittedEvent.AggregateEvent); Assert.Equal(registeringUser.Id, @event.RecordingUserId); Assert.Equal(command.ContactTimestamp, @event.ContactTimestamp); Assert.Equal(CommunicationChannelType.OutgoingEmail, @event.CommunicationChannel); Assert.Equal(command.EmailAddress, @event.EmailAddress); Assert.Equal(command.PhoneNumber, @event.PhoneNumber); Assert.Equal("Andrzej Strzelba", @event.ContactPersonName); Assert.Equal("treść", @event.Content); Assert.Equal("notatka", @event.AdditionalNotes); }
public void Command_must_be_executed_on_aggregate_with_matching_SchoolId() { var school = new SchoolAggregate(SchoolId.New); var recordingUser = new ApplicationUser(); var command = new RecordContact.Command() { SchoolId = SchoolId.New.GetGuid() }; Assert.Throws <AggregateMismatchException>(() => school.RecordContact(command, recordingUser, NodaTime.SystemClock.Instance.GetCurrentInstant())); }
public void CommandMustContain_EnrollmentId_CommunicationChannel_Content_fields() { var enrollment = new EnrollmentAggregate(EnrollmentAggregate.EnrollmentId.New); var command = new RecordContact.Command() { EnrollmentId = enrollment.Id.GetGuid() }; var result = enrollment.RecordContact(command, new Models.Users.ApplicationUser()); Assert.False(result.IsSuccess); var error = Assert.IsType <Error.ValidationFailed>(result.Error); Assert.Equal(2, error.Failures.Count); }
public Result <Nothing, Error> RecordContact(RecordContact.Command command, ApplicationUser recordingUser) { Guard.Against.Null(command, nameof(command)); Guard.Against.Null(recordingUser, nameof(recordingUser)); ValidateIdMatchOrThrow(command.EnrollmentId); return (Validate(new RecordContact.Validator(), command) .Ensure( _ => this.IsNew == false, new Error.ResourceNotFound(CommonErrorMessages.CandidateNotFound)) .Tap(() => Emit(new ContactOccured( recordingUser.Id, command.CommunicationChannel, command.Content, command.AdditionalNotes ?? string.Empty)))); }
public void Request_Timestamp_cannot_be_later_than_current_timestamp() { var school = new SchoolAggregate(SchoolId.New); var registeringUser = new ApplicationUser() { Id = Guid.NewGuid() }; school.RegisterSchool( NodaTime.SystemClock.Instance.GetCurrentInstant() - NodaTime.Duration.FromDays(1), new RegisterSchool.Command() { Name = "I Liceum Ogólnokształcące", City = "Gdańsk", Address = "Wały Piastowskie 6", ContactData = new[] { new ContactData() { Name = "sekretariat", EmailAddress = EmailAddress.Parse("*****@*****.**"), PhoneNumber = PhoneNumber.Parse("58 301-67-34") }, } }, registeringUser); var command = new RecordContact.Command() { SchoolId = school.Id.GetGuid(), ContactTimestamp = NodaTime.SystemClock.Instance.GetCurrentInstant() + NodaTime.Duration.FromDays(1), CommunicationChannel = CommunicationChannelType.OutgoingEmail, EmailAddress = EmailAddress.Parse("*****@*****.**"), ContactPersonName = "Andrzej Strzelba", Content = "treść" }; var result = school.RecordContact(command, new ApplicationUser() { Id = Guid.NewGuid() }, NodaTime.SystemClock.Instance.GetCurrentInstant()); Assert.False(result.IsSuccess); var error = Assert.IsType <Error.DomainError>(result.Error); Assert.Equal(RecordContact_Messages.Contact_timestamp_cannot_be_later_than_current_timestamp, error.Message); }
public void If_CommunicationChannel_is_IncomingEmail__EmailAddress_must_be_provided() { var school = new SchoolAggregate(SchoolId.New); var recordingUser = new ApplicationUser(); var command = new RecordContact.Command() { SchoolId = school.Id.GetGuid(), ContactTimestamp = NodaTime.SystemClock.Instance.GetCurrentInstant() - NodaTime.Duration.FromDays(1), CommunicationChannel = CommunicationChannelType.IncomingEmail, ContactPersonName = "Andrzej Strzelba", Content = "treść" }; var result = school.RecordContact(command, recordingUser, NodaTime.SystemClock.Instance.GetCurrentInstant()); Assert.False(result.IsSuccess); var error = Assert.IsType <Error.ValidationFailed>(result.Error); Assert.Contains(RecordContact_Messages.EmailAddress_cannot_be_empty_when_CommunicationChannel_is_IncomingEmail_or_OutgoingEmail, error.Failures[nameof(command.EmailAddress)]); }
public void Request_must_contain__SchoolId_Timestamp_CommunicationChannel_and_Content() { var school = new SchoolAggregate(SchoolId.With(Guid.Empty)); var recordingUser = new ApplicationUser(); var command = new RecordContact.Command() { ContactPersonName = " ", Content = " " }; var result = school.RecordContact(command, recordingUser, NodaTime.SystemClock.Instance.GetCurrentInstant()); Assert.False(result.IsSuccess); var error = Assert.IsType <Error.ValidationFailed>(result.Error); Assert.Contains(RecordContact_Messages.SchoolId_cannot_be_empty, error.Failures[nameof(command.SchoolId)]); Assert.Contains(RecordContact_Messages.Timestamp_cannot_be_empty, error.Failures[nameof(command.ContactTimestamp)]); Assert.Contains(RecordContact_Messages.CommunicationChannel_cannot_be_empty, error.Failures[nameof(command.CommunicationChannel)]); Assert.Contains(RecordContact_Messages.ContactPersonName_cannot_be_empty, error.Failures[nameof(command.ContactPersonName)]); Assert.Contains(RecordContact_Messages.Content_cannot_be_empty, error.Failures[nameof(command.Content)]); }
public void SchoolId_must_point_to_existing_school() { var school = new SchoolAggregate(SchoolId.New); var recordingUser = new ApplicationUser(); var command = new RecordContact.Command() { SchoolId = school.Id.GetGuid(), ContactTimestamp = NodaTime.SystemClock.Instance.GetCurrentInstant() - NodaTime.Duration.FromDays(1), CommunicationChannel = CommunicationChannelType.OutgoingEmail, EmailAddress = EmailAddress.Parse("*****@*****.**"), ContactPersonName = "Andrzej Strzelba", Content = "treść" }; var result = school.RecordContact(command, recordingUser, NodaTime.SystemClock.Instance.GetCurrentInstant()); Assert.False(result.IsSuccess); var error = Assert.IsType <Error.ResourceNotFound>(result.Error); Assert.Equal(Messages.School_not_found, error.Message); }
public void CommandMustSpecifyExistingEnrollmentId() { // Arrange var id = EnrollmentAggregate.EnrollmentId.New; var enrollment = new EnrollmentAggregate(id); var recordingUser = new ApplicationUser() { Id = Guid.NewGuid() }; var command = new RecordContact.Command() { EnrollmentId = id.GetGuid(), CommunicationChannel = CommunicationChannel.OutgoingEmail, Content = "ala ma kota", AdditionalNotes = "notatka testowa" }; var result = enrollment.RecordContact(command, recordingUser); Assert.False(result.IsSuccess); Assert.IsType <Error.ResourceNotFound>(result.Error); }
public async Task <IActionResult> RecordContact(RecordContact.Command command) { var result = await _engine.Execute(command); return(result.MatchToActionResult(success => Ok())); }