using System; using System.Collections.Generic; using System.Linq; using System.Text; using System.Threading.Tasks; using gehGassiApp.Core.Data; using gehGassiApp.Core.Interfaces; using gehGassiApp.Core.Interfaces.Synchronization; using gehGassiApp.Domain.Common; using gehGassiApp.Domain.Payment; namespace gehGassiApp.Core.Services { /// /// Service der die Verwaltung von Transaktionsgebühren realisiert /// public class TransactionFeeService : ServiceBase, ITransactionFeeService { private readonly ICommunicationService _communicationService; private readonly ISyncInfoPullService _syncInfoPullService; /// /// Erstellt eine Instanz /// /// Instanz eines IUnitOfWork /// Instanz eines ICommunicationService /// Instanz eines ISyncInfoPullService public TransactionFeeService(IUnitOfWork unitOfWork, ICommunicationService communicationService, ISyncInfoPullService syncInfoPullService) : base(unitOfWork) { _communicationService = communicationService; _syncInfoPullService = syncInfoPullService; } /// /// 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 TransactionFee Get(object id, bool noTracking = true) { return Repository.SingleOrDefault(c => c.Id == id.ToString(), noTracking); } /// /// 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) { return await Repository.SingleOrDefaultAsync(c => c.Id == id.ToString(), noTracking).ConfigureAwait(false); } /// /// Gibt eine Transaktionsgebühr für einen bestimmten Zahlungstyp zurück /// /// Zahlungstyp /// Transaktionsgebühr oder null, wenn nicht gefunden public async Task GetAsync(PayInType payinType) { return await Repository.FirstOrDefaultAsync(c => c.PayInType == payinType && c.Deleted == false).ConfigureAwait(false); } #region Pull-Push Implementation /// /// 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(); //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(); var isConnected = await _communicationService.IsConnected(); if (isConnected) { //Zuerst lezte Aktivität holen... DateTimeOffset? lastUpdate = null; var lastSyncInfo = await _syncInfoPullService.GetAsync(nameof(TransactionFee)); if (lastSyncInfo != null) lastUpdate = lastSyncInfo.LastUpdate; var ctsQuery = new CancellationTokenSource(Common.Constants.PushPullTimeout); var transactionFeesResult = await _communicationService.GetTransactionFeesAsync(lastUpdate, accessToken, token); if (transactionFeesResult.Success) { result = await HandleChangesAsync(transactionFeesResult.Value); if (result.LastUpdate != null) await _syncInfoPullService.AddOrUpddateAsync(nameof(TransactionFee), result.LastUpdate.Value).ConfigureAwait(false); } result.LastUpdate ??= lastUpdate; } return result; } #endregion #region Private /// /// Behandeln der Liste von Transaktionsgebühren wenn welche vom Online-Store geholt werden. /// /// Liste der Transaktionsgebühren /// Task private async Task> HandleChangesAsync(List transactionFees) { var result = new SyncResult(); //Je Rasse durchgehen ob was gemacht werden soll foreach (var transactionFee in transactionFees) { var localTransactionFee = await Repository.FirstOrDefaultAsync(c => c.Id == transactionFee.Id, false); if (localTransactionFee != null && localTransactionFee.UpdatedAt < transactionFee.UpdatedAt) { if (localTransactionFee.UpdatedAt >= transactionFee.UpdatedAt) { if (result.LastUpdate == null || result.LastUpdate < localTransactionFee.UpdatedAt) result.LastUpdate = localTransactionFee.UpdatedAt; continue; } var deleted = localTransactionFee.Deleted == false && transactionFee.Deleted; localTransactionFee.Version = transactionFee.Version; localTransactionFee.UpdatedAt = transactionFee.UpdatedAt; localTransactionFee.Deleted = transactionFee.Deleted; localTransactionFee.PayInType = transactionFee.PayInType; localTransactionFee.Percent = transactionFee.Percent; localTransactionFee.Fixed = transactionFee.Fixed; if (result.LastUpdate == null || result.LastUpdate < localTransactionFee.UpdatedAt) result.LastUpdate = localTransactionFee.UpdatedAt; if (!deleted) result.Updated.Add(localTransactionFee); else result.Deleted.Add(localTransactionFee); Repository.Update(localTransactionFee); } if (localTransactionFee == null) { localTransactionFee = new TransactionFee() { Id = transactionFee.Id, Version = transactionFee.Version, UpdatedAt = transactionFee.UpdatedAt, Deleted = transactionFee.Deleted, PayInType = transactionFee.PayInType, Percent = transactionFee.Percent, Fixed = transactionFee.Fixed }; Repository.Add(localTransactionFee); if (result.LastUpdate == null || result.LastUpdate < localTransactionFee.UpdatedAt) result.LastUpdate = localTransactionFee.UpdatedAt; result.Added.Add(localTransactionFee); } } if (result.HasChanges) { try { await CommitAsync().ConfigureAwait(false); } catch (Exception ex) { var err = ex.Message; } } return result; } #endregion } }