using gehGassiApp.Core.Interfaces; using System; using System.Collections.Generic; using System.Linq; using System.Text; using System.Text.Json; using System.Threading.Tasks; using gehGassi.Dto; using gehGassi.Dto.Common; using gehGassiApp.Core.Data; using gehGassiApp.Core.Helper; using gehGassiApp.Domain.Users; using gehGassiApp.Core.Interfaces.Synchronization; using gehGassiApp.Core.Mapper; using gehGassiApp.Domain.Common; using gehGassiApp.Core.Services.Synchronization; using gehGassiApp.Core.Resources; using gehGassi.Dto.Reporting; namespace gehGassiApp.Core.Services { /// /// Service der die Verwaltung des Benutzers ermöglicht /// public class UserService : ServiceBase, IUserService { private readonly ICommunicationService _communicationService; private readonly ISyncInfoPushService _pushService; private readonly ISyncInfoPullService _pullService; private readonly IRepository _appUserRepository; /// /// Erstellt eine Instanz /// /// Instanz eines IUnitOfWork /// Instanz eines ICommunicationService /// Instanz eines ISyncInfoPushService /// Instanz eines ISyncInfoPullService public UserService(IUnitOfWork unitOfWork, ICommunicationService communicationService, ISyncInfoPushService pushService, ISyncInfoPullService pullService) : base(unitOfWork) { _communicationService = communicationService; _pushService = pushService; _pullService = pullService; _appUserRepository = unitOfWork.GetRepository(); } /// /// Gibt eine Entität anhand der eindeutigen Id zurück /// /// Id der Entität /// Gibt an ob NoTRacking verwendet werden soll. Es werden keine Entitäten im EF-Speicher gehalten /// Entität oder null, wenn nicht gefunden public override User Get(object id, bool noTracking = true) { //Bewusst nicht implementiert throw new NotImplementedException(); } /// /// Gibt eine Entität anhand der eindeutigen Id zurück /// /// Id der Entität /// Gibt an ob NoTRacking verwendet werden soll. Es werden keine Entitäten im EF-Speicher gehalten /// Entität oder null, wenn nicht gefunden public override async Task GetAsync(object id, bool noTracking = true) { //Bewusst nicht implementiert await Task.Delay(1); throw new NotImplementedException(); } /// /// Gibt den aktuellen Benutzer zurück /// /// Aktueller Benutzer oder null, wenn noch keiner vorhanden public async Task GetAsync() { var user = await Repository.FirstOrDefaultAsync(c => c.Id != "", false).ConfigureAwait(false); return user; } /// /// Hinzufügen oder aktualisieren des Benutzers /// /// Benutzer der hinzugefügt oder aktualisiert werden soll /// public async Task CreateOrUpdateAsync(User user) { var foundUser = await GetAsync().ConfigureAwait(false); if (foundUser == null) { Repository.Add(user); await CommitAsync(); return user; } foundUser.FirstName = user.FirstName; foundUser.LastName = user.LastName; foundUser.Roles = user.Roles; foundUser.Photo = user.Photo; foundUser.RegistrationDate = user.RegistrationDate; foundUser.LastLoginDate = user.LastLoginDate; foundUser.AppUserId = user.AppUserId; Repository.Update(foundUser); await CommitAsync().ConfigureAwait(false); return foundUser; } /// /// Prüft für einen übergebenen Benutzernamen ob es sich um den gespeicherten Benutzer handelt /// /// Benutzername (E-Mail Adresse) /// UserCheckResult public async Task CheckAsync(string userName) { var user = await Repository.FirstOrDefaultAsync(c => c.Id != "", true).ConfigureAwait(false); if (user != null) { return string.Equals(user.UserName, userName, StringComparison.CurrentCultureIgnoreCase) ? UserCheckResult.IsCurrentUser : UserCheckResult.IsOtherUser; } return UserCheckResult.Empty; } /// /// Gibt den aktuellen App-User zurück. /// /// AppUser oder null wenn nicht gefunden public async Task GetAppUserAsync() { var appUser = await _appUserRepository.FirstOrDefaultAsync(c => c.Id != "").ConfigureAwait(false); return appUser; } /// /// Gibt den aktuellen App-User zurück. /// /// Tracking /// AppUser oder null wenn nicht gefunden public async Task GetAppUserAsync(bool noTracking) { var appUser = await _appUserRepository.FirstOrDefaultAsync(c => c.Id != "", noTracking).ConfigureAwait(false); return appUser; } /// /// Gibt den aktuellen App-User zurück /// Versucht auch online - wenn lokal nicht vorhanden /// /// Aktuelles Accesstoken /// CancellationToken /// Wenn true, wird in jedem Fall die Online-Abfrage verwendet /// AppUser oder null wenn nicht gefunden public async Task GetAppUserAsync(string accessToken, CancellationToken token, bool forceOnline) { //Zuerst DB if (forceOnline) { var isConnected = await _communicationService.IsConnected(); if (isConnected) { var appUserResult = await _communicationService.GetAppUserAsync(accessToken, token); if (appUserResult.Success) { var appUserUpdated = await CreateOrUpdateAppUserAsync(appUserResult.Value); await _pullService.AddOrUpddateAsync(nameof(AppUser), DateTimeOffset.UtcNow); return appUserUpdated; } } } var appUser = await _appUserRepository.FirstOrDefaultAsync(c => c.Id != "").ConfigureAwait(false); if (appUser != null) return appUser; return null; } /// /// Hinzufügen oder aktualisieren eines App-Users /// /// App-User /// AppUser public async Task CreateOrUpdateAppUserAsync(AppUser appUser) { var foundUser = await _appUserRepository.FirstOrDefaultAsync(c => c.Id != "", false).ConfigureAwait(false); if (foundUser == null) { _appUserRepository.Add(appUser); await CommitAsync(); return appUser; } if (appUser.UpdatedAt > foundUser.UpdatedAt) { foundUser.Type = appUser.Type; foundUser.Title = appUser.Title; foundUser.FirstName = appUser.FirstName; foundUser.LastName = appUser.LastName; foundUser.Sex = appUser.Sex; foundUser.BirthDate = appUser.BirthDate; foundUser.Photo = appUser.Photo; foundUser.Contact = appUser.Contact; foundUser.Address = appUser.Address; foundUser.Lat = appUser.Lat; foundUser.Lng = appUser.Lng; foundUser.SocialMedia = appUser.SocialMedia; foundUser.Locked = appUser.Locked; foundUser.LockedUntil = appUser.LockedUntil; foundUser.UpdatedAt = appUser.UpdatedAt; foundUser.Deleted = appUser.Deleted; foundUser.TermsAccepted = appUser.TermsAccepted; foundUser.TermsAcceptedDate = appUser.TermsAcceptedDate; foundUser.PrivacyAccepted = appUser.PrivacyAccepted; foundUser.PrivacyAcceptedDate = appUser.PrivacyAcceptedDate; foundUser.PaymentTermsAccepted = appUser.PaymentTermsAccepted; foundUser.PaymentTermsAcceptedDate = appUser.PaymentTermsAcceptedDate; foundUser.NationalityCode = appUser.NationalityCode ?? string.Empty; foundUser.MainResidenceCode = appUser.MainResidenceCode ?? string.Empty; foundUser.PaymentId = appUser.PaymentId; foundUser.KycPassed = appUser.KycPassed; foundUser.KycPassedDate = appUser.KycPassedDate; foundUser.Verified = appUser.Verified; foundUser.VerifiedDate = appUser.VerifiedDate; foundUser.AutoPayout = appUser.AutoPayout; _appUserRepository.Update(foundUser); var changes = await CommitAsync().ConfigureAwait(false); } return await GetAppUserAsync(); } /// /// Aktualisieren eines App-Users. /// Online wird versucht. Wenn nicht möglich wird ein Delta erstellt. /// /// App-User /// Aktuelles Accesstoken /// CancellationToken /// App-User public async Task UpdateAppUserAsync(AppUser appUser, string accessToken, CancellationToken token) { //Zuerst in der DB aktualisieren var foundUser = await _appUserRepository.FirstOrDefaultAsync(c => c.Id == appUser.Id, false); foundUser.FirstName = appUser.FirstName; foundUser.LastName = appUser.LastName; foundUser.Sex = appUser.Sex; foundUser.BirthDate = appUser.BirthDate; foundUser.Photo = appUser.Photo; foundUser.Contact.Mobile = appUser.Contact.Mobile; foundUser.Contact.Phone = appUser.Contact.Phone; foundUser.Address.AddressLine1 = appUser.Address.AddressLine1; foundUser.Address.AddressLine2 = appUser.Address.AddressLine2; foundUser.Address.Zip = appUser.Address.Zip; foundUser.Address.City = appUser.Address.City; foundUser.Address.State = appUser.Address.State; foundUser.Address.CountryCode = appUser.Address.CountryCode; foundUser.NationalityCode = appUser.NationalityCode ?? string.Empty; foundUser.MainResidenceCode = appUser.MainResidenceCode ?? string.Empty; foundUser.AutoPayout = appUser.AutoPayout; foundUser.UpdatedAt = DateTimeOffset.UtcNow; if (appUser.Lat != 0 && appUser.Lng != 0) { foundUser.Lat = appUser.Lat; foundUser.Lng = appUser.Lng; } _appUserRepository.Update(foundUser); await CommitAsync().ConfigureAwait(false); var appUserDto = foundUser.ToDto(); var photoFileName = string.Empty; byte[] photo = null; if (!string.IsNullOrWhiteSpace(foundUser.Photo)) { if (!foundUser.Photo.StartsWithHttp()) { //Datei laden und in byte array umwandeln if (File.Exists(foundUser.Photo)) { await using var stream = File.OpenRead(foundUser.Photo); using var memoryStream = new MemoryStream(); await stream.CopyToAsync(memoryStream, token); photo = memoryStream.ToArray(); photoFileName = Path.GetFileName(appUserDto.Photo); } } } var isConnected = await _communicationService.IsConnected(); if (isConnected) { var updateResult = await _communicationService.UpdateAppUserAsync(appUserDto,photoFileName,photo,accessToken, token); if (updateResult.Success) { //Alles gut nichts weglegen //Für den Pull-Service das Update-Datum setzen await _pullService.AddOrUpddateAsync(nameof(AppUser), foundUser.UpdatedAt).ConfigureAwait(false); } else { //Weglegen und später versuchen await _pushService.AddAsync(nameof(AppUser), foundUser.Id, SyncOperation.Edit, foundUser).ConfigureAwait(false); } } else { //Weglegen und später versuchen await _pushService.AddAsync(nameof(AppUser), foundUser.Id, SyncOperation.Edit, foundUser).ConfigureAwait(false); } return foundUser; } /// /// Setzen des App-User Types für einen AppUser. /// Immer online und nur wenn erfolgreich auch ein Update lokal! /// /// Id des AppUsers /// Typ der gesetzt werden soll /// Aktuelles Accesstoken /// CancellationToken /// CommunicationResult public async Task> SetAppUserTypeAsync(string appUserId, AppUserType appUserType, string accessToken, CancellationToken token) { var result = new CommunicationResult(); var hasConnection = await _communicationService.IsConnected(); if (hasConnection) { var model = new SetAppUserTypeDto() { Id = appUserId, Type = (AppUserTypeDto)appUserType, UpdatedAt = DateTimeOffset.UtcNow }; var serverResult = await _communicationService.SetAppUserTypeAsync(model, accessToken, token); if (serverResult.Success && serverResult.Value) { //jetzt auch lokal die Änderung speichern var appUser = await GetAppUserAsync(false); appUser.Type = appUserType; appUser.UpdatedAt = model.UpdatedAt; _appUserRepository.Update(appUser); await CommitAsync().ConfigureAwait(false); await _pullService.AddOrUpddateAsync(nameof(AppUser), model.UpdatedAt); } return serverResult; } else { result.Success = false; result.ErrorCode = CommunicationErrors.ServerNoConnection; result.ErrorMessage = Errors.Server_NoConnection; } return result; } /// /// Setzen des App-User Types für einen AppUser. /// Immer online und nur wenn erfolgreich auch ein Update lokal! /// /// Id des AppUsers /// Typ der gesetzt werden soll /// Nationalität /// Land des Hauptwohnsitzes /// AGB Paymentprovider akzeptiert /// Aktuelles Accesstoken /// CancellationToken /// CommunicationResult public async Task> SetAppUserTypeAsync(string appUserId, AppUserType appUserType, string nationality, string mainResidence, bool paymentTermsAccepted, string accessToken, CancellationToken token) { var result = new CommunicationResult(); var hasConnection = await _communicationService.IsConnected(); if (hasConnection) { var model = new SetAppUserTypeExDto() { Id = appUserId, Type = (AppUserTypeDto)appUserType, NationalityCode = nationality, MainResidenceCode = mainResidence, PaymentTermsAccepted = paymentTermsAccepted, PaymentTermsAcceptedDate = DateTimeOffset.UtcNow, UpdatedAt = DateTimeOffset.UtcNow }; var serverResult = await _communicationService.SetAppUserTypeAsync(model, accessToken, token); if (serverResult.Success && serverResult.Value != null) { //jetzt auch lokal die Änderung speichern var appUser = await GetAppUserAsync(false); appUser.Type = appUserType; appUser.NationalityCode = serverResult.Value.NationalityCode; appUser.MainResidenceCode = serverResult.Value.MainResidenceCode; appUser.PaymentTermsAccepted = serverResult.Value.PaymentTermsAccepted; appUser.PaymentTermsAcceptedDate = serverResult.Value.PaymentTermsAcceptedDate; appUser.PaymentId = serverResult.Value.PaymentId; appUser.UpdatedAt = model.UpdatedAt; _appUserRepository.Update(appUser); await CommitAsync().ConfigureAwait(false); await _pullService.AddOrUpddateAsync(nameof(AppUser), model.UpdatedAt); result.Success = true; result.Value = true; } } else { result.Success = false; result.ErrorCode = CommunicationErrors.ServerNoConnection; result.ErrorMessage = Errors.Server_NoConnection; } return result; } /// /// Hinzufügen eines Payment-Users. Für Hundebesitzer wenn sie noch keine PaymentId haben /// /// Id des AppUsers /// Nationalität /// Land des Hauptwohnsitzes /// AGB Paymentprovider akzeptiert /// Aktuelles Accesstoken /// CancellationToken /// CommunicationResult public async Task> AddPaymentUserAsync(string appUserId, string nationality, string mainResidence, bool paymentTermsAccepted, string accessToken, CancellationToken token) { var result = new CommunicationResult(); var hasConnection = await _communicationService.IsConnected(); if (hasConnection) { var model = new AddPaymentUserDto() { Id = appUserId, NationalityCode = nationality, MainResidenceCode = mainResidence, PaymentTermsAccepted = paymentTermsAccepted, PaymentTermsAcceptedDate = DateTimeOffset.UtcNow }; var serverResult = await _communicationService.AddPaymentUserAsync(model, accessToken, token); if (serverResult.Success && serverResult.Value != null) { //jetzt auch lokal die Änderung speichern var appUser = await GetAppUserAsync(false); appUser.NationalityCode = serverResult.Value.NationalityCode; appUser.MainResidenceCode = serverResult.Value.MainResidenceCode; appUser.PaymentTermsAccepted = serverResult.Value.PaymentTermsAccepted; appUser.PaymentTermsAcceptedDate = serverResult.Value.PaymentTermsAcceptedDate; appUser.PaymentId = serverResult.Value.PaymentId; appUser.UpdatedAt = serverResult.Value.UpdatedAt; _appUserRepository.Update(appUser); await CommitAsync().ConfigureAwait(false); await _pullService.AddOrUpddateAsync(nameof(AppUser), appUser.UpdatedAt); result.Success = true; result.Value = true; } } else { result.Success = false; result.ErrorCode = CommunicationErrors.ServerNoConnection; result.ErrorMessage = Errors.Server_NoConnection; } return result; } /// /// Setzen der Bankverbindungs-ID für einen AppUser. /// /// Id des App-Users /// ID der Bankverbindung /// Datum letzte Aktualisierung /// App-User public async Task SetBankAccountAsync(string appUserId, string bankId, DateTimeOffset updatedAt) { var appUser = await GetAppUserAsync(false); appUser.BankId = bankId; appUser.UpdatedAt = updatedAt; _appUserRepository.Update(appUser); await CommitAsync().ConfigureAwait(false); await _pullService.AddOrUpddateAsync(nameof(AppUser), appUser.UpdatedAt); return appUser; } /// /// Blockieren eines App-Users am Server /// /// Id des App-Users der die Blockierung vornimmt /// Id des App-Users der blockiert wird /// Aktuelles Accesstoken /// CancellationToken /// CommunicationResult public async Task> BlockAppUserAsync(string appUserId, string blockedAppUserId, string accessToken, CancellationToken token) { var result = new CommunicationResult(); var hasConnection = await _communicationService.IsConnected(); if (hasConnection) { var model = new BlockCreateDto() { BlockingAppUserId = appUserId, BlockedAppUserId = blockedAppUserId }; var serverResult = await _communicationService.BlockAppUserAsync(model, accessToken, token); return serverResult; } else { result.Success = false; result.ErrorCode = CommunicationErrors.ServerNoConnection; result.ErrorMessage = Errors.Server_NoConnection; } return result; } /// /// Aufheben der Blockierung eines App-Users am Server /// /// Id des App-Users der die Blockierung vorgenommen hat /// Id des App-Users dessen Blockierung aufgehoben wird /// Aktuelles Accesstoken /// CancellationToken /// CommunicationResult public async Task> UnblockAppUserAsync(string appUserId, string blockedAppUserId, string accessToken, CancellationToken token) { var result = new CommunicationResult(); var hasConnection = await _communicationService.IsConnected(); if (hasConnection) { var model = new BlockRemoveDto() { BlockingAppUserId = appUserId, BlockedAppUserId = blockedAppUserId }; var serverResult = await _communicationService.UnblockAppUserAsync(model, accessToken, token); return serverResult; } else { result.Success = false; result.ErrorCode = CommunicationErrors.ServerNoConnection; result.ErrorMessage = Errors.Server_NoConnection; } return result; } /// /// Holen von blockierten App-Usern /// /// Abfrageobjekt /// Aktuelle Position /// Aktuelles Accesstoken /// CancellationToken /// ListCommunicationResult public async Task>> GetBlockedAppUsersAsync(BlockedQueryDto query, LocationDto location, string accessToken, CancellationToken token) { var result = new ListCommunicationResult>() { Value = new List() }; var isConnected = await _communicationService.IsConnected(); if (isConnected) { query.Location = location; var queryResult = await _communicationService.GetBlockedAppUsersAsync(query, accessToken, token); if (queryResult.Success && queryResult.Value.Count >= 1) { return queryResult; } } else { result.Success = false; result.ErrorCode = CommunicationErrors.ServerNoConnection; result.ErrorMessage = Errors.Server_NoConnection; } return result; } /// /// Melden eines App-Users durch einen anderen bei Verfehlungen oder anstößigen Inhalten /// /// Id des App-Users der die Meldung vornimmt /// Id des App-Users der gemeldet wird /// Betroffener Bereich /// Id des Bereichs /// Optional: zweite Id falls nötig /// Bild beanstanded /// Name beanstanded /// Text beanstanded /// Nachricht beanstanded /// Adresse beanstanded /// Typ der Meldung /// Email-Adresse des meldenen Benutzers für Kontaktaufnahme /// Anmerkungen des meldenden Benutzers /// Chat-Nachricht wenn es eine betrifft /// Art der bBlockierung /// Darf für Rückfragen kontaktiert werden /// Aktuelles Accesstoken /// CancellationToken /// ListCommunicationResult public async Task> ReportAppUserAsync(string appUserId, string reportedAppUserId, AppUserReportSection section, string sectionId, string sectionId2, bool reportedImage, bool reportedName, bool reportedText, bool reportedMessage, bool reportedAddress, AppUserReportType type, string email, string comment, string message, AppUserReportBlockType blockType, bool contactAllowed, string accessToken, CancellationToken token) { var result = new CommunicationResult(); var hasConnection = await _communicationService.IsConnected(); if (hasConnection) { var model = new AppUserReportDto() { ReportingAppUserId = appUserId, ReportedAppUserId = reportedAppUserId, Section = section.ToDto(), SectionId = sectionId, SectionId2 = sectionId2, ReportedImage = reportedImage, ReportedName = reportedName, ReportedText = reportedText, ReportedMessage = reportedMessage, ReportedAddress = reportedAddress, Type = type.ToDto(), Email = email, Comment = comment, Message = message, BlockType = blockType.ToDto(), ContactAllowed = contactAllowed }; var serverResult = await _communicationService.ReportAppUserAsync(model, accessToken, token); return serverResult; } else { result.Success = false; result.ErrorCode = CommunicationErrors.ServerNoConnection; result.ErrorMessage = Errors.Server_NoConnection; } return result; } /// /// Holen der Daten vom lokalen Speicher die noch nicht synchronisiert wurden und senden an den Server /// /// Aktuelles Accesstoken /// CancellationToken /// Task public async Task> PushAsync(string accessToken, CancellationToken token) { var result = new SyncResult(); if (await _pushService.HasOpenAsync(nameof(AppUser)) > 0) { var deltas = await _pushService.GetAllAsync(nameof(AppUser)).ConfigureAwait(false); if (deltas.Any()) { var isConnected = await _communicationService.IsConnected(); if (!isConnected) return result; deltas = deltas.OrderBy(c => c.DateTime).ToList(); foreach (var syncInfoPush in deltas) { //Es gibt hier ur Update... daher alles andere ignorieren if (syncInfoPush.Operation != SyncOperation.Edit) { await _pushService.RemoveAsync(syncInfoPush.Id).ConfigureAwait(false); continue; } try { if (!string.IsNullOrWhiteSpace(syncInfoPush.Value)) { var appUser = JsonSerializer.Deserialize(syncInfoPush.Value, new JsonSerializerOptions(JsonSerializerDefaults.Web)); //Jetzt Update senden... var appUserDto = appUser.ToDto(); var photoFileName = string.Empty; byte[] photo = null; if (!string.IsNullOrWhiteSpace(appUser.Photo)) { if (!appUser.Photo.StartsWithHttp()) { //Datei laden und in byte array umwandeln if (File.Exists(appUser.Photo)) { await using var stream = File.OpenRead(appUser.Photo); using var memoryStream = new MemoryStream(); await stream.CopyToAsync(memoryStream, token); photo = memoryStream.ToArray(); photoFileName = Path.GetFileName(appUserDto.Photo); } } } var updateResult = await _communicationService.UpdateAppUserAsync(appUserDto, photoFileName, photo, accessToken, token); if (updateResult.Success) { //Aktualisierung durchgeführt. await _pullService.AddOrUpddateAsync(nameof(AppUser), appUser.UpdatedAt).ConfigureAwait(false); await _pushService.RemoveAsync(syncInfoPush.Id).ConfigureAwait(false); } else { //TODO: Prüfen!!!! //Derzeiut egal welcher Fehler vorliegt, weg damit //Aktualisierung durchgeführt. await _pullService.AddOrUpddateAsync(nameof(AppUser), appUser.UpdatedAt).ConfigureAwait(false); await _pushService.RemoveAsync(syncInfoPush.Id).ConfigureAwait(false); } //Else ist nichts tun, konnte nicht übertragen werden. } else { await _pushService.RemoveAsync(syncInfoPush.Id).ConfigureAwait(false); } } catch (Exception ex) { System.Diagnostics.Debug.WriteLine(ex.Message); await _pushService.RemoveAsync(syncInfoPush.Id).ConfigureAwait(false); } } } } //Es gibt hier kein Push! await Task.Delay(1); return result; } /// /// Holen der letzten Daten vom Server und Synchronisieren mit den lokalen Daten /// /// Sprache /// Aktuelles Accesstoken /// CancellationToken /// Task public async Task> PullAsync(string language, string accessToken, CancellationToken token) { var result = new SyncResult(); //Zuerst immer online... var isConnected = await _communicationService.IsConnected(); if (isConnected) { //Zuerst lezte Aktivität holen... DateTimeOffset? lastUpdate = null; var lastSyncInfo = await _pullService.GetAsync(nameof(AppUser)).ConfigureAwait(false); if (lastSyncInfo != null) lastUpdate = lastSyncInfo.LastUpdate; var ctsQuery = new CancellationTokenSource(Common.Constants.PushPullTimeout); var appUserResult = await _communicationService.GetAppUserSyncAsync(lastUpdate, accessToken, token); if (appUserResult.Success) { if (appUserResult.Value != null) { var appUser = await _appUserRepository.GetAsync(appUserResult.Value.Id).ConfigureAwait(false); if (appUser != null) { appUser.FirstName = appUserResult.Value.FirstName; appUser.LastName = appUserResult.Value.LastName; appUser.Sex = appUserResult.Value.Sex; appUser.BirthDate = appUserResult.Value.BirthDate; appUser.Photo = appUserResult.Value.Photo; appUser.Contact.Mobile = appUserResult.Value.Contact.Mobile; appUser.Contact.Phone = appUserResult.Value.Contact.Phone; appUser.Address.AddressLine1 = appUserResult.Value.Address.AddressLine1; appUser.Address.AddressLine2 = appUserResult.Value.Address.AddressLine2; appUser.Address.Zip = appUserResult.Value.Address.Zip; appUser.Address.City = appUserResult.Value.Address.City; appUser.Address.State = appUserResult.Value.Address.State; appUser.Address.CountryCode = appUserResult.Value.Address.CountryCode; appUser.Lat = appUserResult.Value.Lat; appUser.Lng = appUserResult.Value.Lng; appUser.Type = appUserResult.Value.Type; appUser.TermsAccepted = appUserResult.Value.TermsAccepted; appUser.TermsAcceptedDate = appUserResult.Value.TermsAcceptedDate; appUser.PrivacyAccepted = appUserResult.Value.PrivacyAccepted; appUser.PrivacyAcceptedDate = appUserResult.Value.PrivacyAcceptedDate; appUser.PaymentTermsAccepted = appUserResult.Value.PaymentTermsAccepted; appUser.PaymentTermsAcceptedDate = appUserResult.Value.PaymentTermsAcceptedDate; appUser.NationalityCode = appUserResult.Value.NationalityCode; appUser.MainResidenceCode = appUserResult.Value.MainResidenceCode; appUser.PaymentId = appUserResult.Value.PaymentId; appUser.KycPassed = appUserResult.Value.KycPassed; appUser.KycPassedDate = appUserResult.Value.KycPassedDate; appUser.BankId = appUserResult.Value.BankId; appUser.Verified = appUserResult.Value.Verified; appUser.VerifiedDate = appUserResult.Value.VerifiedDate; appUser.AutoPayout = appUserResult.Value.AutoPayout; appUser.UpdatedAt = DateTimeOffset.UtcNow; _appUserRepository.Update(appUser); await CommitAsync().ConfigureAwait(false); result.Updated.Add(appUser); result.LastUpdate = appUserResult.Value.UpdatedAt; await _pullService.AddOrUpddateAsync(nameof(AppUser), appUserResult.Value.UpdatedAt).ConfigureAwait(false); } } } result.LastUpdate ??= lastUpdate; } return result; } } }