Exemplo n.º 1
0
        public async Task <IActionResult> DeactivateLocality([Required][FromBody] DeactivateLocalityRequest deactivateLocalityRequest,
                                                             CancellationToken cancellationToken = default)
        {
            var(_, isFailure, error) = await _localityManagementService.DeactivateLocality(deactivateLocalityRequest, cancellationToken);

            if (isFailure)
            {
                return(BadRequestWithProblemDetails(error));
            }

            return(NoContent());
        }
        public async Task <Result> DeactivateLocality(DeactivateLocalityRequest deactivateLocalityRequest, CancellationToken cancellationToken = default)
        {
            var deactivatedLocalityHtId = deactivateLocalityRequest.DeactivatedLocalityHtId;
            var localityToReplaceHtId   = deactivateLocalityRequest.LocalityToReplaceHtId;

            return(await GetLocalityWithAccommodationsAndZones(deactivatedLocalityHtId)
                   .Bind(dl => GetLocalityToReplace(dl, localityToReplaceHtId))
                   .Bind(ValidateLocalities)
                   .BindWithTransaction(_dbContext, l => Result.Success(l)
                                        .Tap(UpdateDeactivatedLocalityAccommodations)
                                        .Tap(UpdateDeactivatedLocalityZones)
                                        .Tap(DeactivateLocality))
                   .Tap(PublishLocalityChanges));


            async Task <Result <Locality> > GetLocalityWithAccommodationsAndZones(string htId)
            {
                var(_, isGettingIdFailure, id, gettingIdError) = GetId(htId, MapperLocationTypes.Locality);
                if (isGettingIdFailure)
                {
                    return(Result.Failure <Locality>(gettingIdError));
                }

                var locality = await _dbContext.Localities
                               .Include(l => l.Accommodations)
                               .Include(l => l.LocalityZones)
                               .SingleOrDefaultAsync(l => l.Id == id && l.IsActive, cancellationToken);

                if (locality is null)
                {
                    return(Result.Failure <Locality>($"Failed to retrieve the locality by the requested htId '{htId}'"));
                }

                return(locality !);
            }

            async Task <Result <(Locality, Locality)> > GetLocalityToReplace(Locality deactivatedLocality, string localityToReplaceHtId)
            {
                var(_, isGettingIdFailure, localityToReplaceId, gettingIdError) = GetId(localityToReplaceHtId, MapperLocationTypes.Locality);
                if (isGettingIdFailure)
                {
                    return(Result.Failure <(Locality, Locality)>(gettingIdError));
                }

                var localityToReplace = await _dbContext.Localities.Include(l => l.Country)
                                        .SingleOrDefaultAsync(l => l.Id == localityToReplaceId && l.IsActive, cancellationToken);

                if (localityToReplace is null)
                {
                    return(Result.Failure <(Locality, Locality)>($"Failed to retrieve the substitutional locality by htId '{localityToReplaceHtId}"));
                }

                return(deactivatedLocality, localityToReplace);
            }

            Result <(Locality deactivatedLocality, Locality substitutionalLocality)> ValidateLocalities(
                (Locality deactivatedLocality, Locality substitutionalLocality) localities)
            {
                if (localities.deactivatedLocality.CountryId != localities.substitutionalLocality.CountryId)
                {
                    return(Result.Failure <(Locality, Locality)>($"Country of the original locality and substitutional locality mustn't be different"));
                }

                return(localities);
            }

            async Task UpdateDeactivatedLocalityAccommodations((Locality deactivatedLocality, Locality localityToReplace) localities)
            {
                var deactivatedLocality = localities.deactivatedLocality;
                var localityToReplace   = localities.localityToReplace;
                var accommodations      = deactivatedLocality.Accommodations.ToList();

                await UpdateAccommodationsLocalityId(localityToReplace, accommodations, cancellationToken);
            }

            async Task UpdateDeactivatedLocalityZones((Locality deactivatedLocality, Locality localityToReplace) localities)
            {
                var deactivatedLocality = localities.deactivatedLocality;
                var localityToReplace   = localities.localityToReplace;
                var localityZones       = deactivatedLocality.LocalityZones;

                if (!localityZones.Any())
                {
                    return;
                }

                foreach (var localityZone in localityZones)
                {
                    localityZone.Modified   = DateTimeOffset.UtcNow;
                    localityZone.LocalityId = localityToReplace.Id;
                }

                _dbContext.UpdateRange(localityZones);
                await _dbContext.SaveChangesAsync(cancellationToken);
            }

            async Task DeactivateLocality((Locality deactivatedLocality, Locality localityToReplace) localities)
            {
                var deactivatedLocality = localities.deactivatedLocality;

                deactivatedLocality.Modified = DateTimeOffset.UtcNow;
                deactivatedLocality.IsActive = false;
                _dbContext.Update(deactivatedLocality);
                await _dbContext.SaveChangesAsync(cancellationToken);
            }

            async Task PublishLocalityChanges((Locality deactivatedLocality, Locality localityToReplace) localities)
            {
                var deactivatedLocality = localities.deactivatedLocality;
                var localityToReplace   = localities.localityToReplace;

                await _localityChangePublisher.PublishRemovedLocalities(new() { deactivatedLocality.Id });

                await _localityChangePublisher.PublishUpdatedLocalities(new()
                {
                    new(localityToReplace.Id,
                        localityToReplace.Names.En,
                        localityToReplace.Country.Names.En,
                        localityToReplace.Country.Code)
                });
            }
        }