public MultilingualAccommodation Correct(AccommodationDataForCorrection accommodationDataForCorrection) { var normalizedSupplierAccommodationDetails = accommodationDataForCorrection.SuppliersRawAccommodationData .ToDictionary(sa => sa.Key, sa => _multilingualDataHelper.NormalizeAccommodation(sa.Value, accommodationDataForCorrection.CountryNames, accommodationDataForCorrection.LocalityNames, accommodationDataForCorrection.LocalityZoneNames)); var name = MergeMultilingualData(accommodationDataForCorrection.SuppliersPriorities[AccommodationDataTypes.Name], normalizedSupplierAccommodationDetails.ToDictionary(s => s.Key, s => s.Value.Name) !, accommodationDataForCorrection.ManualCorrectedData.Name, string.IsNullOrEmpty); var category = MergeMultilingualData(accommodationDataForCorrection.SuppliersPriorities[AccommodationDataTypes.Category], normalizedSupplierAccommodationDetails.ToDictionary(s => s.Key, s => s.Value.Category) !, accommodationDataForCorrection.ManualCorrectedData.Category, string.IsNullOrEmpty); var rating = MergeData(accommodationDataForCorrection.SuppliersPriorities[AccommodationDataTypes.Rating], normalizedSupplierAccommodationDetails.ToDictionary(s => s.Key, s => s.Value.Rating), accommodationDataForCorrection.ManualCorrectedData.Rating, r => r == 0); var contactInfo = MergeContactInfo(accommodationDataForCorrection.SuppliersPriorities[AccommodationDataTypes.ContactInfo], normalizedSupplierAccommodationDetails, accommodationDataForCorrection.ManualCorrectedData); var locationInfo = MergeLocationInfo(accommodationDataForCorrection.SuppliersPriorities[AccommodationDataTypes.LocationInfo], normalizedSupplierAccommodationDetails, accommodationDataForCorrection.ManualCorrectedData, accommodationDataForCorrection.CountryNames, accommodationDataForCorrection.LocalityNames, accommodationDataForCorrection.LocalityZoneNames); var photos = MergeData(accommodationDataForCorrection.SuppliersPriorities[AccommodationDataTypes.Photos], normalizedSupplierAccommodationDetails.ToDictionary(s => s.Key, s => s.Value.Photos), accommodationDataForCorrection.ManualCorrectedData.Photos, p => p == null ! || !p.Any()); var textualDescriptions = MergeData(accommodationDataForCorrection.SuppliersPriorities[AccommodationDataTypes.TextualDescriptions], normalizedSupplierAccommodationDetails.ToDictionary(s => s.Key, s => s.Value.TextualDescriptions), accommodationDataForCorrection.ManualCorrectedData.TextualDescriptions, p => p == null ! || !p.Any()); var additionalInfo = MergeMultilingualData(accommodationDataForCorrection.SuppliersPriorities[AccommodationDataTypes.AdditionalInfo], normalizedSupplierAccommodationDetails.ToDictionary(s => s.Key, s => s.Value.AdditionalInfo) !, accommodationDataForCorrection.ManualCorrectedData.AdditionalInfo, p => p == null ! || !p.Any()); var accommodationAmenities = MergeMultilingualData( accommodationDataForCorrection.SuppliersPriorities[AccommodationDataTypes.AccommodationAmenities], normalizedSupplierAccommodationDetails.ToDictionary(s => s.Key, s => s.Value.AccommodationAmenities) !, accommodationDataForCorrection.ManualCorrectedData.AccommodationAmenities, p => p == null ! || !p.Any()); var scheduleInfo = MergeScheduleInfo(accommodationDataForCorrection.SuppliersPriorities[AccommodationDataTypes.Schedule], normalizedSupplierAccommodationDetails, accommodationDataForCorrection.ManualCorrectedData); var propertyType = MergeData(accommodationDataForCorrection.SuppliersPriorities[AccommodationDataTypes.PropertyType], normalizedSupplierAccommodationDetails.ToDictionary(s => s.Key, s => s.Value.Type), accommodationDataForCorrection.ManualCorrectedData.Type, t => t == 0); var hasDirectContractList = normalizedSupplierAccommodationDetails.Select(ac => ac.Value.HasDirectContract).ToList(); hasDirectContractList.Add(accommodationDataForCorrection.ManualCorrectedData.HasDirectContract); var hasDirectContract = MergeBoolData(hasDirectContractList); return(new MultilingualAccommodation ( string.Empty, name: name, category: category, location: locationInfo, photos: photos, rating: rating, type: propertyType, accommodationAmenities: accommodationAmenities, contacts: contactInfo, additionalInfo: additionalInfo, schedule: scheduleInfo, textualDescriptions: textualDescriptions, hasDirectContract: hasDirectContract, isActive: true )); }
public async Task CorrectAccommodations(List <RichAccommodationDetails> notCorrectedAccommodations, CancellationToken cancellationToken = default) { var accommodationsToPublish = new List <(AccommodationData accommodation, int localityId)>(); await GetRawAccommodations() .Bind(CorrectAll) .BindWithTransaction(_context, () => SaveCorrected() .Tap(PublishCorrected) .Tap(SaveCorrectionLogs)); async Task <Result <List <RawAccommodation> > > GetRawAccommodations() { var supplierAccommodationIds = notCorrectedAccommodations .SelectMany(ac => ac.SupplierAccommodationCodes).Select(ac => ac.Value).ToList(); var rawAccommodations = await _context.RawAccommodations.Where(ra => supplierAccommodationIds.Contains(ra.SupplierAccommodationId)) .Select(ra => new RawAccommodation { Accommodation = ra.Accommodation, Supplier = ra.Supplier, SupplierAccommodationId = ra.SupplierAccommodationId, LocalityNames = ra.LocalityNames, LocalityZoneNames = ra.LocalityZoneNames }) .ToListAsync(cancellationToken); return(rawAccommodations); } async Task <Result> CorrectAll(List <RawAccommodation> rawAccommodations) { foreach (var accommodation in notCorrectedAccommodations) { await GetAccommodationSuppliersData(accommodation, rawAccommodations) .Bind(suppliersData => CorrectAccommodation(accommodation, suppliersData)) .Bind(GetCorrectedAccommodationKeyData) .Bind(data => CollectDataForPublish(accommodation, data.CorrectedData, data.KeyData)) .Bind(data => UpdateAccommodation(accommodation, data.CorrectedData, data.KeyData)) .Tap(correctedData => CollectCorrectionLog(accommodation.Id, correctedData)); } return(Result.Success()); } Result <(MultilingualAccommodation CorrectedData, AccommodationKeyData KeyData)> GetCorrectedAccommodationKeyData(MultilingualAccommodation correctedData) => (correctedData, _multilingualDataHelper.GetAccommodationKeyData(correctedData)); async Task <Result> SaveCorrected() { await _context.SaveChangesAsync(cancellationToken); return(Result.Success()); } async Task PublishCorrected() { await _accommodationChangePublisher.PublishUpdated(accommodationsToPublish); } async Task SaveCorrectionLogs() { await _accommodationChangeLogCollectorService.SaveCollectedEventLogs(cancellationToken); } Result <Dictionary <string, MultilingualAccommodation> > GetAccommodationSuppliersData(RichAccommodationDetails accommodation, List <RawAccommodation> rawAccommodations) { var supplierAccommodations = (from ra in rawAccommodations join sa in accommodation.SupplierAccommodationCodes on ra.SupplierAccommodationId equals sa.Value where ra.Supplier == sa.Key select ra).ToList(); return((from sa in supplierAccommodations join acs in accommodation.SupplierAccommodationCodes on new { Supplier = sa.Supplier, SupplierAccommodationId = sa.SupplierAccommodationId } equals new { Supplier = acs.Key, SupplierAccommodationId = acs.Value } select sa).ToDictionary(a => a.Supplier, a => JsonConvert.DeserializeObject <MultilingualAccommodation>(a.Accommodation.RootElement .ToString() !))); } async Task <Result <MultilingualAccommodation> > CorrectAccommodation(RichAccommodationDetails accommodation, Dictionary <string, MultilingualAccommodation> supplierAccommodations) { var dataForCorrection = new AccommodationDataForCorrection { SuppliersRawAccommodationData = supplierAccommodations, ManualCorrectedData = accommodation.AccommodationWithManualCorrections, CountryNames = accommodation.Country.Names, LocalityNames = accommodation.Locality.Names, LocalityZoneNames = accommodation.LocalityZone?.Names, SuppliersPriorities = accommodation.SuppliersPriority.Any() ? accommodation.SuppliersPriority : await GetSupplierPriorities() }; return(_dataCorrectionHelper.Correct(dataForCorrection)); } Result <(MultilingualAccommodation CorrectedData, AccommodationKeyData KeyData)> CollectDataForPublish(RichAccommodationDetails accommodation, MultilingualAccommodation correctedData, AccommodationKeyData keyData) { var dataToPublish = Convert(accommodation.Id, accommodation.CountryCode, keyData); if (!dataToPublish.Equals(Convert(accommodation.Id, accommodation.CountryCode, accommodation.KeyData))) { accommodationsToPublish.Add((dataToPublish, accommodation.LocalityId ?? default)); } return(correctedData, keyData); } Result <MultilingualAccommodation> UpdateAccommodation(RichAccommodationDetails accommodation, MultilingualAccommodation correctedData, AccommodationKeyData keyData) { var dbAccommodation = new RichAccommodationDetails { Id = accommodation.Id }; _context.Accommodations.Attach(dbAccommodation); var dbEntry = _context.Entry(dbAccommodation); dbAccommodation.IsCorrected = true; dbAccommodation.FinalAccommodation = correctedData; dbAccommodation.HasDirectContract = correctedData.HasDirectContract; dbAccommodation.KeyData = keyData; dbAccommodation.Modified = DateTimeOffset.UtcNow; dbEntry.Property(p => p.FinalAccommodation).IsModified = true; dbEntry.Property(p => p.HasDirectContract).IsModified = true; dbEntry.Property(p => p.IsCorrected).IsModified = true; dbEntry.Property(p => p.Modified).IsModified = true; dbEntry.Property(p => p.KeyData).IsModified = true; return(correctedData); } void CollectCorrectionLog(int accommodationId, MultilingualAccommodation correctedData) => _accommodationChangeLogCollectorService.CollectDataCorrectionEvent(accommodationId, AccommodationChangeEventSources.Updater, correctedData); }