public async Task PublishVenueUpload_StatusIsProcessedWithErrors_ReturnsUploadHasErrors()
        {
            // Arrange
            var provider = await TestData.CreateProvider();

            var user = await TestData.CreateUser(providerId : provider.ProviderId);

            var(venueUpload, venueUploadRows) = await TestData.CreateVenueUpload(
                provider.ProviderId,
                createdBy : user,
                UploadStatus.ProcessedWithErrors);

            var fileUploadProcessor = new FileUploadProcessor(
                SqlQueryDispatcherFactory,
                Mock.Of <BlobServiceClient>(),
                Clock,
                new RegionCache(SqlQueryDispatcherFactory),
                new ExecuteImmediatelyBackgroundWorkScheduler(Fixture.ServiceScopeFactory));

            // Act
            var result = await fileUploadProcessor.PublishVenueUploadForProvider(provider.ProviderId, user);

            // Assert
            result.Status.Should().Be(PublishResultStatus.UploadHasErrors);
        }
        public async Task PublishVenueUpload_RevalidationAddsSupplementaryRows_PublishesSuccessfully()
        {
            // Arrange
            var provider = await TestData.CreateProvider();

            var user = await TestData.CreateUser(providerId : provider.ProviderId);

            var(venueUpload, venueUploadRows) = await TestData.CreateVenueUpload(
                provider.ProviderId,
                createdBy : user,
                UploadStatus.ProcessedSuccessfully,
                rowBuilder =>
            {
                rowBuilder.AddRow(record =>
                {
                    record.VenueName        = "Venue1";
                    record.ProviderVenueRef = "VENUE1";
                });
            });

            // Ensure we have a record in the Postcodes table for extracting lat/lng
            var postcodePosition = (Latitude : 1d, Longitude : 2d);

            foreach (var postcode in venueUploadRows.Select(r => r.Postcode).Distinct())
            {
                await TestData.CreatePostcodeInfo(postcode, postcodePosition.Latitude, postcodePosition.Longitude);
            }

            // Add a new venue for the provider and link a T-Level to it (so the venue cannot be removed by the publish).
            // Revalidation should kick in and add a supplementary row (without any validation errors).

            Clock.UtcNow += TimeSpan.FromDays(1);

            var oldVenue2 = await TestData.CreateVenue(provider.ProviderId, createdBy : user, venueName : "Venue2", providerVenueRef : "VENUE2");

            var tLevelDefinitions = await TestData.CreateInitialTLevelDefinitions();

            await TestData.CreateTLevel(
                provider.ProviderId,
                tLevelDefinitions.First().TLevelDefinitionId,
                new[] { oldVenue2.VenueId },
                createdBy : user);

            var fileUploadProcessor = new FileUploadProcessor(
                SqlQueryDispatcherFactory,
                Mock.Of <BlobServiceClient>(),
                Clock,
                new RegionCache(SqlQueryDispatcherFactory),
                new ExecuteImmediatelyBackgroundWorkScheduler(Fixture.ServiceScopeFactory));

            // Act
            var result = await fileUploadProcessor.PublishVenueUploadForProvider(provider.ProviderId, user);

            // Assert
            result.Status.Should().Be(PublishResultStatus.Success);
            result.PublishedCount.Should().Be(2);
        }
        public async Task PublishVenueUpload_CanBePublished_UpsertsRowsArchivesUnmatchedVenuesAndSetsStatusToPublished()
        {
            // Arrange
            var provider = await TestData.CreateProvider();

            var user = await TestData.CreateUser(providerId : provider.ProviderId);

            var oldVenue1 = await TestData.CreateVenue(provider.ProviderId, createdBy : user, venueName : "Venue 1", providerVenueRef : "VENUE1");

            var oldVenue2 = await TestData.CreateVenue(provider.ProviderId, createdBy : user, venueName : "Venue 2");

            var(venueUpload, venueUploadRows) = await TestData.CreateVenueUpload(
                provider.ProviderId,
                createdBy : user,
                UploadStatus.ProcessedSuccessfully,
                rowBuilder =>
            {
                // Add two rows; one matching `oldVenue` and one that doesn't match an existing venue

                rowBuilder.AddRow(record =>
                {
                    record.VenueName        = "Venue 1";
                    record.ProviderVenueRef = "VENUE1";
                    record.VenueId          = oldVenue1.VenueId;
                });

                rowBuilder.AddRow(record => record.VenueName = "New venue 1");
            });

            // Ensure we have a record in the Postcodes table for extracting lat/lng
            var postcodePosition = (Latitude : 1d, Longitude : 2d);

            foreach (var postcode in venueUploadRows.Select(r => r.Postcode).Distinct())
            {
                await TestData.CreatePostcodeInfo(postcode, postcodePosition.Latitude, postcodePosition.Longitude);
            }

            var fileUploadProcessor = new FileUploadProcessor(
                SqlQueryDispatcherFactory,
                Mock.Of <BlobServiceClient>(),
                Clock,
                new RegionCache(SqlQueryDispatcherFactory),
                new ExecuteImmediatelyBackgroundWorkScheduler(Fixture.ServiceScopeFactory));

            // Act
            var result = await fileUploadProcessor.PublishVenueUploadForProvider(provider.ProviderId, user);

            // Assert
            result.Status.Should().Be(PublishResultStatus.Success);
            result.PublishedCount.Should().Be(2);

            await WithSqlQueryDispatcher(async dispatcher =>
            {
                venueUpload = await dispatcher.ExecuteQuery(new GetVenueUpload()
                {
                    VenueUploadId = venueUpload.VenueUploadId
                });
                venueUpload.UploadStatus.Should().Be(UploadStatus.Published);
                venueUpload.PublishedOn.Should().Be(Clock.UtcNow);

                var providerVenues = await dispatcher.ExecuteQuery(new GetVenuesByProvider()
                {
                    ProviderId = provider.ProviderId
                });

                providerVenues.Should().BeEquivalentTo(new[]
                {
                    new Venue()
                    {
                        VenueId          = oldVenue1.VenueId,
                        VenueName        = venueUploadRows[0].VenueName,
                        ProviderId       = provider.ProviderId,
                        ProviderUkprn    = provider.Ukprn,
                        ProviderVenueRef = venueUploadRows[0].ProviderVenueRef,
                        AddressLine1     = venueUploadRows[0].AddressLine1,
                        AddressLine2     = venueUploadRows[0].AddressLine2,
                        Town             = venueUploadRows[0].Town,
                        County           = venueUploadRows[0].County,
                        Postcode         = venueUploadRows[0].Postcode,
                        Latitude         = postcodePosition.Latitude,
                        Longitude        = postcodePosition.Longitude,
                        Email            = venueUploadRows[0].Email,
                        Telephone        = venueUploadRows[0].Telephone,
                        Website          = venueUploadRows[0].Website
                    },
                    new Venue()
                    {
                        VenueId          = venueUploadRows[1].VenueId,
                        VenueName        = venueUploadRows[1].VenueName,
                        ProviderId       = provider.ProviderId,
                        ProviderUkprn    = provider.Ukprn,
                        ProviderVenueRef = venueUploadRows[1].ProviderVenueRef,
                        AddressLine1     = venueUploadRows[1].AddressLine1,
                        AddressLine2     = venueUploadRows[1].AddressLine2,
                        Town             = venueUploadRows[1].Town,
                        County           = venueUploadRows[1].County,
                        Postcode         = venueUploadRows[1].Postcode,
                        Latitude         = postcodePosition.Latitude,
                        Longitude        = postcodePosition.Longitude,
                        Email            = venueUploadRows[1].Email,
                        Telephone        = venueUploadRows[1].Telephone,
                        Website          = venueUploadRows[1].Website
                    },
                });
            });
        }