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);
        }
Esempio n. 8
0
        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()));
        }