public async Task Build_Period_For_Apprenticeship_And_PriceEpisode(
            [Frozen] Mock <IApprenticeshipRepository> repository,
            PriceEpisodeStatusChangeBuilder sut,
            EarningFailedDataLockMatching dataLockEvent,
            List <EarningPeriod> periods,
            List <DataLockFailure> dataLockFailures,
            List <ApprenticeshipModel> apprenticeships)
        {
            CommonTestSetup(repository, dataLockEvent, periods, apprenticeships, dataLockFailures);

            var result = await sut.Build(
                new List <DataLockEvent> {
                dataLockEvent
            },
                new List <(string identifier, PriceEpisodeStatus status)>
            {
                (dataLockEvent.PriceEpisodes[0].Identifier, PriceEpisodeStatus.New)
            },
                new List <PriceEpisodeStatusChange>(), dataLockEvent.CollectionPeriod.AcademicYear);

            result.First().Periods.Should().ContainEquivalentOf(new
            {
                DataLockEventId      = result.First().DataLock.DataLockEventId,
                IsPayable            = false,
                TransactionTypesFlag = 1
            });
        }
        public async Task Builds_an_add_event_with_status(
            PriceEpisodeStatusChangeBuilder sut,
            [Frozen] Mock <IApprenticeshipRepository> repository,
            PayableEarningEvent dataLock,
            List <EarningPeriod> periods,
            List <DataLockFailure> dataLockFailures,
            List <ApprenticeshipModel> apprenticeships)
        {
            CommonTestSetup(repository, dataLock, periods, apprenticeships, dataLockFailures);
            var priceEpisode = dataLock.PriceEpisodes[0];

            var result = await sut.Build(
                new List <DataLockEvent> {
                dataLock
            },
                new List <(string identifier, PriceEpisodeStatus status)>
            {
                (priceEpisode.Identifier, PriceEpisodeStatus.Updated)
            },
                new List <PriceEpisodeStatusChange>(), dataLock.CollectionPeriod.AcademicYear);

            result.Should().ContainEquivalentOf(new
            {
                DataLock = new
                {
                    PriceEpisodeIdentifier = priceEpisode.Identifier,
                    Status = PriceEpisodeStatus.Updated,
                }
            });
        }
        public async Task Builds_an_event_with_errors(
            DataLockErrorCode errorCode,
            string description,
            [Frozen] Mock <IApprenticeshipRepository> repository,
            PriceEpisodeStatusChangeBuilder sut,
            EarningFailedDataLockMatching dataLock,
            List <EarningPeriod> periods,
            List <DataLockFailure> dataLockFailures,
            ApprenticeshipModel apprenticeships)
        {
            CommonTestSetup(repository, dataLock, periods, new List <ApprenticeshipModel> {
                apprenticeships
            }, dataLockFailures);
            var priceEpisode = dataLock.PriceEpisodes[0];

            periods[0].DataLockFailures[0].DataLockError = errorCode;

            var result = await sut.Build(
                new List <DataLockEvent> {
                dataLock
            },
                new List <(string identifier, PriceEpisodeStatus status)>
            {
                (priceEpisode.Identifier, PriceEpisodeStatus.New)
            },
                new List <PriceEpisodeStatusChange>(), dataLock.CollectionPeriod.AcademicYear);

            result.Should().NotBeEmpty();
            result[0].Errors.Should().ContainEquivalentOf(new
            {
                DataLockEventId   = result[0].DataLock.DataLockEventId,
                ErrorCode         = errorCode.ToString(),
                SystemDescription = description,
            });
        }
        public async Task Builds_an_add_event_with_no_errors(
            [Frozen] Mock <IApprenticeshipRepository> repository,
            PriceEpisodeStatusChangeBuilder sut,
            PayableEarningEvent dataLock,
            List <EarningPeriod> periods,
            List <ApprenticeshipModel> apprenticeships)
        {
            CommonTestSetup(repository, dataLock, periods, apprenticeships);

            var priceEpisode = dataLock.PriceEpisodes[0];

            priceEpisode.TotalNegotiatedPrice3 = 1;

            var result = await sut.Build(
                new List <DataLockEvent> {
                dataLock
            },
                new List <(string identifier, PriceEpisodeStatus status)>
            {
                (priceEpisode.Identifier, PriceEpisodeStatus.New)
            },
                new List <PriceEpisodeStatusChange>(), dataLock.CollectionPeriod.AcademicYear);

            result.Should().ContainEquivalentOf(new
            {
                DataLock = new { PriceEpisodeIdentifier = priceEpisode.Identifier },
                Errors   = new LegacyDataLockEventError[0]
            });
        }
        public async Task No_datalocks_or_current_price_episodes_builds_no_events(
            [Frozen] Mock <IApprenticeshipRepository> repository,
            PriceEpisodeStatusChangeBuilder sut)
        {
            var result = await sut.Build(
                new List <DataLockEvent>(),
                new List <(string identifier, PriceEpisodeStatus status)>(),
                new List <PriceEpisodeStatusChange>(), 2019);

            result.Should().BeEmpty();
        }
        public async Task Build_PriceEpisode_Removed_Event(
            [Frozen] Mock <IApprenticeshipRepository> repository,
            PriceEpisodeStatusChangeBuilder sut,
            EarningFailedDataLockMatching dataLockEvent,
            List <EarningPeriod> periods,
            List <DataLockFailure> dataLockFailures,
            List <ApprenticeshipModel> apprenticeships)
        {
            CommonTestSetup(repository, dataLockEvent, periods, apprenticeships, dataLockFailures);
            var episodeStatusChange = new List <PriceEpisodeStatusChange>
            {
                new PriceEpisodeStatusChange
                {
                    DataLock = new LegacyDataLockEvent
                    {
                        PriceEpisodeIdentifier = dataLockEvent.PriceEpisodes[0].Identifier,
                        Status       = PriceEpisodeStatus.New,
                        UKPRN        = dataLockEvent.Ukprn,
                        ULN          = dataLockEvent.Learner.Uln,
                        AcademicYear = "1920"
                    }
                }
            };

            dataLockEvent.CollectionPeriod.AcademicYear = 1920;

            var result = await sut.Build(
                new List <DataLockEvent> {
                dataLockEvent
            },
                new List <(string identifier, PriceEpisodeStatus status)>
            {
                (dataLockEvent.PriceEpisodes[0].Identifier, PriceEpisodeStatus.Removed)
            },
                episodeStatusChange, dataLockEvent.CollectionPeriod.AcademicYear);

            result.Should().ContainEquivalentOf(new
            {
                DataLock = new
                {
                    PriceEpisodeIdentifier = dataLockEvent.PriceEpisodes[0].Identifier,
                    Status = PriceEpisodeStatus.Removed,
                    UKPRN  = dataLockEvent.Ukprn,
                    ULN    = dataLockEvent.Learner.Uln
                },
            });
        }
        public async Task Builds_an_add_event_with_data_from_datalock(
            [Frozen] Mock <IApprenticeshipRepository> repository,
            PriceEpisodeStatusChangeBuilder sut,
            PayableEarningEvent dataLock,
            List <EarningPeriod> periods,
            List <DataLockFailure> dataLockFailures,
            List <ApprenticeshipModel> apprenticeships)
        {
            CommonTestSetup(repository, dataLock, periods, apprenticeships, dataLockFailures);
            var priceEpisode = dataLock.PriceEpisodes[0];

            dataLock.IlrFileName = "bob";
            var result = await sut.Build(
                new List <DataLockEvent> {
                dataLock
            },
                new List <(string identifier, PriceEpisodeStatus status)>
            {
                (priceEpisode.Identifier, PriceEpisodeStatus.New)
            },
                new List <PriceEpisodeStatusChange>(), dataLock.CollectionPeriod.AcademicYear);

            result.Should().ContainEquivalentOf(new
            {
                DataLock = new
                {
                    PriceEpisodeIdentifier = priceEpisode.Identifier,
                    AcademicYear           = dataLock.CollectionPeriod.AcademicYear.ToString(),
                    UKPRN                     = dataLock.Ukprn,
                    EventSource               = 1,
                    HasErrors                 = false,
                    ULN                       = dataLock.Learner.Uln,
                    LearnRefNumber            = dataLock.Learner.ReferenceNumber,
                    IlrFrameworkCode          = dataLock.LearningAim.FrameworkCode,
                    IlrPathwayCode            = dataLock.LearningAim.PathwayCode,
                    IlrProgrammeType          = dataLock.LearningAim.ProgrammeType,
                    IlrStandardCode           = dataLock.LearningAim.StandardCode,
                    SubmittedDateTime         = dataLock.IlrSubmissionDateTime,
                    AimSeqNumber              = dataLock.LearningAim.SequenceNumber,
                    IlrPriceEffectiveFromDate = priceEpisode.EffectiveTotalNegotiatedPriceStartDate,
                    IlrPriceEffectiveToDate   = priceEpisode.ActualEndDate.GetValueOrDefault(priceEpisode.PlannedEndDate),
                    IlrFileName               = "bob",
                    IlrStartDate              = priceEpisode.CourseStartDate,
                }
            });
        }
        public async Task Build_PriceEpisode_Should_not_have_remove_event_twice(
            [Frozen] Mock <IApprenticeshipRepository> repository,
            PriceEpisodeStatusChangeBuilder sut,
            EarningFailedDataLockMatching dataLockEvent,
            List <EarningPeriod> periods,
            List <DataLockFailure> dataLockFailures,
            List <ApprenticeshipModel> apprenticeships)
        {
            CommonTestSetup(repository, dataLockEvent, periods, apprenticeships, dataLockFailures);

            var result = await sut.Build(
                new List <DataLockEvent> {
                dataLockEvent
            },
                new List <(string identifier, PriceEpisodeStatus status)>(),
                new List <PriceEpisodeStatusChange>(), dataLockEvent.CollectionPeriod.AcademicYear);

            result.Should().BeEmpty();
        }
        public async Task Built_event_should_have_distinct_errors(
            [Frozen] Mock <IApprenticeshipRepository> repository,
            PriceEpisodeStatusChangeBuilder sut,
            EarningFailedDataLockMatching dataLock,
            EarningPeriod period,
            ApprenticeshipModel apprenticeships)
        {
            var periods = new List <EarningPeriod> {
                period
            };

            var dLockFailures = new List <DataLockFailure>
            {
                new DataLockFailure
                {
                    ApprenticeshipId = apprenticeships.Id,
                    DataLockError    = DataLockErrorCode.DLOCK_03,
                    ApprenticeshipPriceEpisodeIds = new List <long> {
                        apprenticeships.ApprenticeshipPriceEpisodes[0].Id
                    }
                },
                new DataLockFailure
                {
                    ApprenticeshipId = apprenticeships.Id,
                    DataLockError    = DataLockErrorCode.DLOCK_07,
                    ApprenticeshipPriceEpisodeIds = apprenticeships.ApprenticeshipPriceEpisodes.Select(x => x.Id).ToList(),
                },
                new DataLockFailure
                {
                    ApprenticeshipId = apprenticeships.Id,
                    DataLockError    = DataLockErrorCode.DLOCK_06,
                    ApprenticeshipPriceEpisodeIds = apprenticeships.ApprenticeshipPriceEpisodes.Select(x => x.Id).ToList(),
                },
            };

            dataLock.OnProgrammeEarnings = new List <OnProgrammeEarning>
            {
                new OnProgrammeEarning
                {
                    Type = OnProgrammeEarningType.Learning,
                },
                new OnProgrammeEarning
                {
                    Type = OnProgrammeEarningType.Completion,
                }
            };

            CommonTestSetup(repository, dataLock, periods, new List <ApprenticeshipModel> {
                apprenticeships
            }, dLockFailures);


            var priceEpisode = dataLock.PriceEpisodes[0];

            dataLock.OnProgrammeEarnings[1].Periods = periods.AsReadOnly();


            var result = await sut.Build(
                new List <DataLockEvent> {
                dataLock
            },
                new List <(string identifier, PriceEpisodeStatus status)>
            {
                (priceEpisode.Identifier, PriceEpisodeStatus.New)
            },
                new List <PriceEpisodeStatusChange>(), dataLock.CollectionPeriod.AcademicYear);

            result.Should().NotBeEmpty();
            result[0].Errors.Should().HaveCount(3);
            result[0].Errors.Should().BeEquivalentTo(new List <LegacyDataLockEventError>
            {
                new LegacyDataLockEventError
                {
                    DataLockEventId = result[0].DataLock.DataLockEventId,
                    ErrorCode       = DataLockErrorCode.DLOCK_03.ToString(),
                },
                new LegacyDataLockEventError
                {
                    DataLockEventId = result[0].DataLock.DataLockEventId,
                    ErrorCode       = DataLockErrorCode.DLOCK_07.ToString(),
                },
                new LegacyDataLockEventError
                {
                    DataLockEventId = result[0].DataLock.DataLockEventId,
                    ErrorCode       = DataLockErrorCode.DLOCK_06.ToString(),
                },
            }, options => options.Excluding(o => o.SystemDescription));
        }
        public async Task Build_Should_Generate_Update_Event_For_Previous_AcademicYear_PriceEpisode(
            [Frozen] Mock <IApprenticeshipRepository> repository,
            PriceEpisodeStatusChangeBuilder sut,
            EarningFailedDataLockMatching dataLockEvent1920,
            EarningFailedDataLockMatching dataLockEvent2021,
            List <EarningPeriod> periods,
            List <DataLockFailure> dataLockFailures,
            List <ApprenticeshipModel> apprenticeships)
        {
            CommonTestSetup(repository, dataLockEvent1920, periods, apprenticeships, dataLockFailures);
            CommonTestSetup(repository, dataLockEvent2021, periods, apprenticeships, dataLockFailures);

            apprenticeships.RemoveRange(1, 2);

            var episodeStatusChange = new List <PriceEpisodeStatusChange>
            {
                new PriceEpisodeStatusChange
                {
                    DataLock = new LegacyDataLockEvent
                    {
                        PriceEpisodeIdentifier = dataLockEvent1920.PriceEpisodes[0].Identifier,
                        Status       = PriceEpisodeStatus.New,
                        UKPRN        = dataLockEvent1920.Ukprn,
                        ULN          = dataLockEvent1920.Learner.Uln,
                        AcademicYear = "1920"
                    }
                },
                new PriceEpisodeStatusChange
                {
                    DataLock = new LegacyDataLockEvent
                    {
                        PriceEpisodeIdentifier = dataLockEvent1920.PriceEpisodes[1].Identifier,
                        Status       = PriceEpisodeStatus.Updated,
                        UKPRN        = dataLockEvent1920.Ukprn,
                        ULN          = dataLockEvent1920.Learner.Uln,
                        AcademicYear = "1920"
                    }
                },
                new PriceEpisodeStatusChange
                {
                    DataLock = new LegacyDataLockEvent
                    {
                        PriceEpisodeIdentifier = dataLockEvent2021.PriceEpisodes[0].Identifier,
                        Status       = PriceEpisodeStatus.Updated,
                        UKPRN        = dataLockEvent2021.Ukprn,
                        ULN          = dataLockEvent2021.Learner.Uln,
                        AcademicYear = "2021"
                    }
                }
            };

            dataLockEvent1920.CollectionPeriod.AcademicYear = 1920;
            dataLockEvent2021.CollectionPeriod.AcademicYear = 2021;

            var result = await sut.Build(
                new List <DataLockEvent> {
                dataLockEvent1920, dataLockEvent2021
            },
                new List <(string identifier, PriceEpisodeStatus status)>
            {
                (dataLockEvent1920.PriceEpisodes[0].Identifier, PriceEpisodeStatus.Removed),
                (dataLockEvent1920.PriceEpisodes[1].Identifier, PriceEpisodeStatus.Removed),
                (dataLockEvent2021.PriceEpisodes[0].Identifier, PriceEpisodeStatus.Removed)
            },
                episodeStatusChange, dataLockEvent2021.CollectionPeriod.AcademicYear);

            result.Count.Should().Be(3);
            result.Select(s => s.DataLock).Any(x =>
                                               x.PriceEpisodeIdentifier == dataLockEvent1920.PriceEpisodes[0].Identifier &&
                                               x.Status == PriceEpisodeStatus.Updated &&
                                               x.UKPRN == dataLockEvent1920.Ukprn &&
                                               x.ULN == dataLockEvent1920.Learner.Uln &&
                                               x.AcademicYear == "1920"
                                               ).Should().BeTrue();

            result.Select(s => s.DataLock).Any(x =>
                                               x.PriceEpisodeIdentifier == dataLockEvent1920.PriceEpisodes[1].Identifier &&
                                               x.Status == PriceEpisodeStatus.Updated &&
                                               x.UKPRN == dataLockEvent1920.Ukprn &&
                                               x.ULN == dataLockEvent1920.Learner.Uln &&
                                               x.AcademicYear == "1920"
                                               ).Should().BeTrue();

            result.Select(s => s.DataLock).Any(x =>
                                               x.PriceEpisodeIdentifier == dataLockEvent2021.PriceEpisodes[0].Identifier &&
                                               x.Status == PriceEpisodeStatus.Removed &&
                                               x.UKPRN == dataLockEvent2021.Ukprn &&
                                               x.ULN == dataLockEvent2021.Learner.Uln &&
                                               x.AcademicYear == "2021"
                                               ).Should().BeTrue();
        }
        public async Task Build_Should_Not_Generate_Remove_Event_For_Previous_AcademicYear_PriceEpisode(
            [Frozen] Mock <IApprenticeshipRepository> repository,
            PriceEpisodeStatusChangeBuilder sut,
            EarningFailedDataLockMatching dataLockEvent,
            List <EarningPeriod> periods,
            List <DataLockFailure> dataLockFailures,
            List <ApprenticeshipModel> apprenticeships)
        {
            CommonTestSetup(repository, dataLockEvent, periods, apprenticeships, dataLockFailures);
            var episodeStatusChange = new List <PriceEpisodeStatusChange>
            {
                new PriceEpisodeStatusChange
                {
                    DataLock = new LegacyDataLockEvent
                    {
                        PriceEpisodeIdentifier = dataLockEvent.PriceEpisodes[0].Identifier,
                        Status       = PriceEpisodeStatus.New,
                        UKPRN        = dataLockEvent.Ukprn,
                        ULN          = dataLockEvent.Learner.Uln,
                        AcademicYear = "1920"
                    }
                },
                new PriceEpisodeStatusChange
                {
                    DataLock = new LegacyDataLockEvent
                    {
                        PriceEpisodeIdentifier = dataLockEvent.PriceEpisodes[1].Identifier,
                        Status       = PriceEpisodeStatus.New,
                        UKPRN        = dataLockEvent.Ukprn,
                        ULN          = dataLockEvent.Learner.Uln,
                        AcademicYear = "2021"
                    }
                }
            };

            dataLockEvent.CollectionPeriod.AcademicYear = 2021;

            var result = await sut.Build(
                new List <DataLockEvent> {
                dataLockEvent
            },
                new List <(string identifier, PriceEpisodeStatus status)>
            {
                (dataLockEvent.PriceEpisodes[0].Identifier, PriceEpisodeStatus.Removed),
                (dataLockEvent.PriceEpisodes[1].Identifier, PriceEpisodeStatus.Removed)
            },
                episodeStatusChange, dataLockEvent.CollectionPeriod.AcademicYear);

            result.Count.Should().Be(2);
            result.Select(s => s.DataLock).Should().BeEquivalentTo(new
            {
                PriceEpisodeIdentifier = dataLockEvent.PriceEpisodes[0].Identifier,
                Status       = PriceEpisodeStatus.Updated,
                UKPRN        = dataLockEvent.Ukprn,
                ULN          = dataLockEvent.Learner.Uln,
                AcademicYear = "1920"
            }, new
            {
                PriceEpisodeIdentifier = dataLockEvent.PriceEpisodes[1].Identifier,
                Status       = PriceEpisodeStatus.Removed,
                UKPRN        = dataLockEvent.Ukprn,
                ULN          = dataLockEvent.Learner.Uln,
                AcademicYear = "2021"
            });
        }