1441 lines
63 KiB
C#

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Text.Json;
using System.Threading.Tasks;
using gehGassi.Dto.Common;
using gehGassi.Dto;
using gehGassi.Dto.Walks;
using gehGassiApp.Core.Data;
using gehGassiApp.Core.Interfaces;
using gehGassiApp.Core.Interfaces.Synchronization;
using gehGassiApp.Core.Resources;
using gehGassiApp.Domain.Common;
using gehGassiApp.Domain.Users;
using gehGassiApp.Domain.Walks;
using gehGassi.Dto.Ratings;
using gehGassiApp.Core.Mapper;
namespace gehGassiApp.Core.Services
{
/// <summary>
/// Service der die Verwaltung von Walks ermöglicht
/// </summary>
public class WalkService : ServiceBase<Walk>, IWalkService
{
private readonly ICommunicationService _communicationService;
private readonly ISyncInfoPullService _pullService;
private readonly ISyncInfoPushService _pushService;
private readonly ILocationService _locationService;
private readonly IRepository<AppUser> _appUserRepository;
/// <summary>
/// Erstellt eine Instanz
/// </summary>
/// <param name="unitOfWork">Instanz eines IUnitOfWork</param>
/// <param name="communicationService">Instanz eines ICommunicationService</param>
/// <param name="syncInfoPullService">Instanz eines ISyncInfoPullService</param>
/// <param name="syncInfoPushService">Instanz eines ISyncInfoPushService</param>
/// <param name="locationService">Instanz eines ILocationService</param>
public WalkService(IUnitOfWork unitOfWork, ICommunicationService communicationService, ISyncInfoPullService syncInfoPullService, ISyncInfoPushService syncInfoPushService, ILocationService locationService) : base(unitOfWork)
{
_communicationService = communicationService;
_pullService = syncInfoPullService;
_pushService = syncInfoPushService;
_locationService = locationService;
_appUserRepository = unitOfWork.GetRepository<AppUser>();
}
/// <summary>
/// Gibt eine Entität anhand der eindeutigen Id zurück
/// </summary>
/// <param name="id">Id der Entität</param>
/// <param name="noTracking">Gibt an ob NoTRacking verwendet werden soll. Es werden keine Entitäten im EF-Speicher gehalten</param>
/// <returns>Entität oder null, wenn nicht gefunden</returns>
public override Walk Get(object id, bool noTracking = true)
{
throw new NotImplementedException();
}
/// <summary>
/// Gibt eine Entität anhand der eindeutigen Id zurück
/// </summary>
/// <param name="id">Id der Entität</param>
/// <param name="noTracking">Gibt an ob NoTRacking verwendet werden soll. Es werden keine Entitäten im EF-Speicher gehalten</param>
/// <returns>Entität oder null, wenn nicht gefunden</returns>
public override async Task<Walk> GetAsync(object id, bool noTracking = true)
{
await Task.Delay(1);
throw new NotImplementedException();
}
/// <summary>
/// Gibt einen Walk mit Namen aufgelöst zurück. Kommt vom Server
/// </summary>
/// <param name="walkId">Id des Walks</param>
/// <param name="language">Gewünschte Sprache</param>
/// <param name="accessToken">Aktuelles Accesstoken</param>
/// <param name="token">CancellationToken</param>
/// <returns>WalkWithNames oder null, wenn nicht gefunden</returns>
public async Task<CommunicationResult<WalkWithNames>> GetWalkWithNamesAsync(string walkId, string language, string accessToken, CancellationToken token)
{
var result = new CommunicationResult<WalkWithNames>();
result.Success = false;
var isConnected = await _communicationService.IsConnected();
if (isConnected)
{
var queryResult = await _communicationService.GetWalkWithNamesAsync(walkId, language, accessToken, token);
if (queryResult.Success)
{
result.Success = true;
result.Value = queryResult.Value;
return result;
}
}
else
{
result.Success = false;
result.ErrorCode = CommunicationErrors.ServerNoConnection;
result.ErrorMessage = Errors.Server_NoConnection;
}
return result;
}
/// <summary>
/// Gibt den nächsten Walk für einen Hundebesitzer zurück
/// </summary>
/// <param name="ownerId">Id des Hundebesitzers</param>
/// <param name="date">Datum ab wann gesucht werden soll. Normalerweise "Jetzt"</param>
/// <param name="language">Gewünschte Sprache</param>
/// <param name="appMode">Aktueller appMode</param>
/// <param name="location">Aktuelle Position</param>
/// <param name="accessToken">Aktuelles Accesstoken</param>
/// <param name="token">CancellationToken</param>
/// <returns>Nächster Walk oder null, wenn keiner vorhanden</returns>
public async Task<CommunicationResult<WalkWithNames>> GetNextWalkForOwnerAsync(string ownerId, DateTimeOffset date, string language, AppMode appMode, LocationDto location, string accessToken, CancellationToken token)
{
var result = new CommunicationResult<WalkWithNames>();
result.Success = false;
var isConnected = await _communicationService.IsConnected();
if (isConnected)
{
var query = new WalksQueryDto()
{
Location = location,
Language = language,
AppMode = (AppModeDto)appMode,
Take = 1,
Skip = 0,
LastUpdate = null,
DogOwnerId = ownerId,
DogWalkerId = string.Empty,
Date = date,
Status = null,
ServiceType = null,
PaymentStatus = null,
IgnoreCancelled = true,
ForNextWalk = true
};
var queryResult = await _communicationService.GetWalksWithNamesAsync(query, accessToken, token);
if (queryResult.Success && queryResult.Value.Count >= 1)
{
result.Success = true;
result.Value = queryResult.Value.First();
return result;
}
}
else
{
result.Success = false;
result.ErrorCode = CommunicationErrors.ServerNoConnection;
result.ErrorMessage = Errors.Server_NoConnection;
}
return result;
}
/// <summary>
/// Gibt den nächsten Walk für einen Dogwalker zurück
/// </summary>
/// <param name="walkerId">Id des Hundebesitzers</param>
/// <param name="date">Datum ab wann gesucht werden soll. Normalerweise "Jetzt"</param>
/// <param name="language">Gewünschte Sprache</param>
/// <param name="appMode">Aktueller appMode</param>
/// <param name="location">Aktuelle Position</param>
/// <param name="accessToken">Aktuelles Accesstoken</param>
/// <param name="token">CancellationToken</param>
/// <returns>Nächster Walk oder null, wenn keiner vorhanden</returns>
public async Task<CommunicationResult<WalkWithNames>> GetNextWalkForWalkerAsync(string walkerId, DateTimeOffset date, string language, AppMode appMode, LocationDto location, string accessToken, CancellationToken token)
{
var result = new CommunicationResult<WalkWithNames>();
result.Success = false;
var isConnected = await _communicationService.IsConnected();
if (isConnected)
{
var query = new WalksQueryDto()
{
Location = location,
Language = language,
AppMode = (AppModeDto)appMode,
Take = 1,
Skip = 0,
LastUpdate = null,
DogOwnerId = string.Empty,
DogWalkerId = walkerId,
Date = date,
Status = null,
ServiceType = null,
PaymentStatus = null,
IgnoreCancelled = true,
ForNextWalk = true
};
var queryResult = await _communicationService.GetWalksWithNamesWalkerAsync(query, accessToken, token);
if (queryResult.Success && queryResult.Value.Count >= 1)
{
result.Success = true;
result.Value = queryResult.Value.First();
return result;
}
}
else
{
result.Success = false;
result.ErrorCode = CommunicationErrors.ServerNoConnection;
result.ErrorMessage = Errors.Server_NoConnection;
}
return result;
}
/// <summary>
/// Gibt Walks vom Server zurück
/// </summary>
/// <param name="dogOwnerId">Id des Hundebesitzers - angeben wenn für Hundebesitzer</param>
/// <param name="dogWalkerId">Id des Dogwalkers - angeben wenn für DogWalker</param>
/// <param name="date">Datum ab wann gesucht werden soll. Normalerweise "Jetzt", leer für alle</param>
/// <param name="status">Status des Walks, NULL wenn alle</param>
/// <param name="serviceType">Service Type, NULL wenn alle</param>
/// <param name="paymentStatus">Zahlungsstatus, NULL wenn alle</param>
/// <param name="dogFilter">Optinal: Filter Hund</param>
/// <param name="walkerFilter">Optional: Filter Walker</param>
/// <param name="ownerFilter">Optional: Filter Owner</param>
/// <param name="ignoreCancelled">Stornierte ignorieren</param>
/// <param name="ignoreRequested">Sollen Walks die noch eine Anfrage sind, ohne Akzeptiert oder Agelehnt ignorniert werden?</param>
/// <param name="ignoreDeclined">Sollen abgelehnte Anfragen ignoriert werden?</param>
/// <param name="sortOrders">Liste von Sortierangaben</param>
/// <param name="language">Gewünschte Sprache</param>
/// <param name="appMode">Aktueller appMode</param>
/// <param name="location">Aktuelle Position</param>
/// <param name="take">Wie viele Walks sollen abgerufen werden? -1 Wenn nicht anwenden.</param>
/// <param name="skip">Wie viele Walks sollen ausgelassen werden? -1 Wenn nicht anwenden.</param>
/// <param name="accessToken">Aktuelles Accesstoken</param>
/// <param name="token">CancellationToken</param>
/// <returns>Nächster Walk oder null, wenn keiner vorhanden</returns>
public async Task<ListCommunicationResult<List<WalkWithNames>>> GetWalksAsync(string dogOwnerId, string dogWalkerId, DateTimeOffset? date, WalkStatus? status, WalkServiceType? serviceType, PaymentStatus? paymentStatus, string dogFilter, string walkerFilter, string ownerFilter, bool ignoreCancelled, bool ignoreRequested, bool ignoreDeclined, List<DynamicSortOrder> sortOrders, string language, AppMode appMode, LocationDto location, int take, int skip, string accessToken, CancellationToken token)
{
var result = new ListCommunicationResult<List<WalkWithNames>>() { Value = new List<WalkWithNames>() };
var isConnected = await _communicationService.IsConnected();
if (isConnected)
{
var query = new WalksQueryDto()
{
Location = location,
Language = language,
AppMode = (AppModeDto)appMode,
Take = take,
Skip = skip,
LastUpdate = null,
DogOwnerId = dogOwnerId,
DogWalkerId = dogWalkerId,
Date = date,
Status = (WalkStatusDto?)status,
ServiceType = (WalkServiceTypeDto?)serviceType,
PaymentStatus = (PaymentStatusDto?)paymentStatus,
DogFilter = dogFilter,
WalkerFilter = walkerFilter,
OwnerFilter = ownerFilter,
IgnoreCancelled = ignoreCancelled,
IgnoreRequested = ignoreRequested,
IgnoreDeclined = ignoreDeclined
};
query.DynamicSortOrder = sortOrders.ToDto();
var queryResult = await _communicationService.GetWalksWithNamesAsync(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;
}
/// <summary>
/// Gibt Walks vom Server zurück.
/// Sondersituation: Für Walker werden nur Walks mit einem Paymentstatus größer gleich Authorized zurück
/// </summary>
/// <param name="dogOwnerId">Id des Hundebesitzers - angeben wenn für Hundebesitzer</param>
/// <param name="dogWalkerId">Id des Dogwalkers - angeben wenn für DogWalker</param>
/// <param name="date">Datum ab wann gesucht werden soll. Normalerweise "Jetzt", leer für alle</param>
/// <param name="status">Status des Walks, NULL wenn alle</param>
/// <param name="serviceType">Service Type, NULL wenn alle</param>
/// <param name="paymentStatus">Zahlungsstatus, NULL wenn alle</param>
/// <param name="dogFilter">Optinal: Filter Hund</param>
/// <param name="walkerFilter">Optional: Filter Walker</param>
/// <param name="ownerFilter">Optional: Filter Owner</param>
/// <param name="ignoreCancelled">Stornierte ignorieren</param>
/// <param name="ignoreRequested">Sollen Walks die noch eine Anfrage sind, ohne Akzeptiert oder Agelehnt ignorniert werden?</param>
/// <param name="ignoreDeclined">Sollen abgelehnte Anfragen ignoriert werden?</param>
/// <param name="sortOrders">Liste von Sortierangaben</param>
/// <param name="language">Gewünschte Sprache</param>
/// <param name="appMode">Aktueller appMode</param>
/// <param name="location">Aktuelle Position</param>
/// <param name="take">Wie viele Walks sollen abgerufen werden? -1 Wenn nicht anwenden.</param>
/// <param name="skip">Wie viele Walks sollen ausgelassen werden? -1 Wenn nicht anwenden.</param>
/// <param name="accessToken">Aktuelles Accesstoken</param>
/// <param name="token">CancellationToken</param>
/// <returns>Nächster Walk oder null, wenn keiner vorhanden</returns>
public async Task<ListCommunicationResult<List<WalkWithNames>>> GetWalksWalkerAsync(string dogOwnerId, string dogWalkerId, DateTimeOffset? date, WalkStatus? status, WalkServiceType? serviceType, PaymentStatus? paymentStatus, string dogFilter, string walkerFilter, string ownerFilter, bool ignoreCancelled, bool ignoreRequested, bool ignoreDeclined, List<DynamicSortOrder> sortOrders, string language, AppMode appMode, LocationDto location, int take, int skip, string accessToken, CancellationToken token)
{
var result = new ListCommunicationResult<List<WalkWithNames>>() { Value = new List<WalkWithNames>() };
var isConnected = await _communicationService.IsConnected();
if (isConnected)
{
var query = new WalksQueryDto()
{
Location = location,
Language = language,
AppMode = (AppModeDto)appMode,
Take = take,
Skip = skip,
LastUpdate = null,
DogOwnerId = dogOwnerId,
DogWalkerId = dogWalkerId,
Date = date,
Status = (WalkStatusDto?)status,
ServiceType = (WalkServiceTypeDto?)serviceType,
PaymentStatus = (PaymentStatusDto?)paymentStatus,
DogFilter = dogFilter,
WalkerFilter = walkerFilter,
OwnerFilter = ownerFilter,
IgnoreCancelled = ignoreCancelled,
IgnoreRequested = ignoreRequested,
IgnoreDeclined = ignoreDeclined
};
query.DynamicSortOrder = sortOrders.ToDto();
var queryResult = await _communicationService.GetWalksWithNamesWalkerAsync(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;
}
/// <summary>
/// Gibt eine Liste der nächsten Walks, laufende, nicht abgeschlossene, nicht bezahlte usw. für einen Hundebesitzer zurück.
/// </summary>
/// <param name="appUserId">Id des App-Users</param>
/// <param name="date">Datum ab dem gesucht</param>
/// <param name="language">Gewünschte Sprache</param>
/// <param name="skip">Datensätze auslassen</param>
/// <param name="take">Datensätze nehmen</param>
/// <param name="accessToken">Aktuelles Accesstoken</param>
/// <param name="token">CancellationToken</param>
/// <returns>ListCommunicationResult</returns>
public async Task<ListCommunicationResult<List<WalkWithNames>>> GetNextWalksOwnerAsync(string appUserId, DateTimeOffset date, string language, int take, int skip, string accessToken, CancellationToken token)
{
var result = new ListCommunicationResult<List<WalkWithNames>>() { Value = new List<WalkWithNames>() };
var isConnected = await _communicationService.IsConnected();
if (isConnected)
{
var queryResult = await _communicationService.GetNextWalksOwnerAsync(appUserId, date, language, take, skip, 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;
}
/// <summary>
/// Gibt eine Liste der nächsten Walks, laufende, nicht abgeschlossene, nicht bezahlte usw. für einen Walker zurück.
/// </summary>
/// <param name="appUserId">Id des App-Users</param>
/// <param name="date">Datum ab dem gesucht</param>
/// <param name="language">Gewünschte Sprache</param>
/// <param name="skip">Datensätze auslassen</param>
/// <param name="take">Datensätze nehmen</param>
/// <param name="accessToken">Aktuelles Accesstoken</param>
/// <param name="token">CancellationToken</param>
/// <returns>ListCommunicationResult</returns>
public async Task<ListCommunicationResult<List<WalkWithNames>>> GetNextWalksWalkerAsync(string appUserId, DateTimeOffset date, string language, int take, int skip, string accessToken, CancellationToken token)
{
var result = new ListCommunicationResult<List<WalkWithNames>>() { Value = new List<WalkWithNames>() };
var isConnected = await _communicationService.IsConnected();
if (isConnected)
{
var queryResult = await _communicationService.GetNextWalksWalkerAsync(appUserId, date, language, take, skip, 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;
}
/// <summary>
/// Gibt einen Walk zurück, welcher einer öffentlichen Anfrage zugeordnet ist
/// </summary>
/// <param name="publicWalkRequestId">Id der öffentlichen Anfrage</param>
/// <returns>Walk oder null, wenn nicht gefunden</returns>
public async Task<Walk> GetWalkByPublicRequestAsync(string publicWalkRequestId)
{
var localWalk = await Repository.FirstOrDefaultAsync(c => c.PublicWalkRequestId == publicWalkRequestId);
return localWalk;
}
/// <summary>
/// Gibt einen Walk zurück, welcher einer öffentlichen Anfrage zugeordnet ist - nur online
/// </summary>
/// <param name="publicWalkRequestId">Id der öffentlichen Anfrage</param>
/// <returns>Walk oder null, wenn nicht gefunden</returns>
public async Task<CommunicationResult<Walk>> GetWalkByPublicRequestAsync(string publicWalkRequestId, string accessToken, CancellationToken token)
{
var result = new CommunicationResult<Walk>();
result.Success = false;
var isConnected = await _communicationService.IsConnected();
if (isConnected)
{
var queryResult = await _communicationService.GetWalkByPublicRequestAsync(publicWalkRequestId, accessToken, token);
if (queryResult.Success && queryResult.Value != null)
{
result.Success = true;
result.Value = queryResult.Value;
return result;
}
}
else
{
result.Success = false;
result.ErrorCode = CommunicationErrors.ServerNoConnection;
result.ErrorMessage = Errors.Server_NoConnection;
}
return result;
}
/// <summary>
/// Stornieren eines Walks
/// </summary>
/// <param name="walkId">ID des Walks</param>
/// <param name="cancellationSource">Quelle der Stornierung</param>
/// <param name="cancellationReason">Grund der Stornierung</param>
/// <param name="accessToken">Aktuelles Accesstoken</param>
/// <param name="token">CancellationToken</param>
/// <returns>true wenn erfolgreich, false sonst</returns>
public async Task<bool> CancelAsync(string walkId, CancellationSource cancellationSource, string cancellationReason, string accessToken, CancellationToken token)
{
var success = false;
var localWalk = await Repository.FirstOrDefaultAsync(c => c.Id == walkId, false);
var updatedAt = DateTimeOffset.UtcNow;
if (localWalk != null)
{
localWalk.Status = WalkStatus.Cancelled;
localWalk.UpdatedAt = updatedAt;
localWalk.CancelledBy = cancellationSource;
localWalk.CancelledReason = cancellationReason;
Repository.Update(localWalk);
await CommitAsync();
success = true;
}
//Jetzt am Server oder Delta erstellen
var createDelta = true;
var isConnected = await _communicationService.IsConnected();
if (isConnected)
{
var dto = new WalkCancelDto()
{
WalkId = walkId,
UpdatedAt = updatedAt,
CancellationSource = (CancellationSourceDto)cancellationSource,
CancelledReason = cancellationReason
};
var cancelResult = await _communicationService.CancelWalkAsync(dto, accessToken, token);
if (cancelResult.Success)
{
if (cancelResult.Value)
{
success = true;
createDelta = false;
}
}
}
if (createDelta)
{
await _pushService.AddAsync(nameof(Walk), localWalk.Id, SyncOperation.Edit, localWalk).ConfigureAwait(false);
}
return success;
}
/// <summary>
/// Starten eines Walks
/// </summary>
/// <param name="walkId">ID des Walks</param>
/// <param name="accessToken">Aktuelles Accesstoken</param>
/// <param name="token">CancellationToken</param>
/// <returns>true wenn erfolgreich, false sonst</returns>
public async Task<bool> StartAsync(string walkId, string accessToken, CancellationToken token)
{
var success = false;
var localWalk = await Repository.FirstOrDefaultAsync(c => c.Id == walkId, false);
var updatedAt = DateTimeOffset.UtcNow;
if (localWalk != null)
{
localWalk.Status = WalkStatus.Started;
localWalk.Started = updatedAt;
localWalk.UpdatedAt = updatedAt;
Repository.Update(localWalk);
await CommitAsync();
success = true;
}
//Jetzt am Server oder Delta erstellen
var createDelta = true;
var isConnected = await _communicationService.IsConnected();
if (isConnected)
{
var dto = new WalkStartDto()
{
WalkId = walkId,
UpdatedAt = updatedAt
};
var cancelResult = await _communicationService.StartWalkAsync(dto, accessToken, token);
if (cancelResult.Success)
{
if (cancelResult.Value)
{
success = true;
createDelta = false;
}
}
}
if (createDelta)
{
await _pushService.AddAsync(nameof(Walk), localWalk.Id, SyncOperation.Edit, localWalk).ConfigureAwait(false);
}
return success;
}
/// <summary>
/// Abschließen eines Walks
/// </summary>
/// <param name="walkId">ID des Walks</param>
/// <param name="defactation">Kotabsatz?</param>
/// <param name="completedInfo">Info des Walkers zum abschluss</param>
/// <param name="ratingPoints">Punkte für die Bewertung des Walks</param>
/// <param name="ratingComment">Anmerkungen zum Rating des Walks</param>
/// <param name="ratingDogsPoints">Punkte für die Bewertung des Hundes / der Hunde</param>
/// <param name="ratingDogsComment">Anmerkung zum Rating des Hundes / der Hunde</param>
/// <param name="accessToken">Aktuelles Accesstoken</param>
/// <param name="token">CancellationToken</param>
/// <returns>true wenn erfolgreich, false sonst</returns>
public async Task<bool> CompleteAsync(string walkId, bool defactation, string completedInfo, decimal ratingPoints, string ratingComment, decimal ratingDogsPoints, string ratingDogsComment, string accessToken, CancellationToken token)
{
var success = false;
var localWalk = await Repository.FirstOrDefaultAsync(c => c.Id == walkId, false);
var updatedAt = DateTimeOffset.UtcNow;
if (localWalk != null)
{
localWalk.Status = WalkStatus.Completed;
localWalk.Completed = updatedAt;
localWalk.Defactation = defactation;
localWalk.CompletedInfo = completedInfo;
localWalk.UpdatedAt = updatedAt;
Repository.Update(localWalk);
await CommitAsync();
success = true;
}
//Jetzt am Server oder Delta erstellen
var createDelta = true;
var isConnected = await _communicationService.IsConnected();
if (isConnected)
{
var dto = new WalkCompleteDto()
{
WalkId = walkId,
CompletedInfo = completedInfo,
Defactation = defactation,
RatingInfo = ratingComment,
RatingPoints = ratingPoints,
RatingDogsPoints = ratingDogsPoints,
RatingDogsInfo = ratingDogsComment,
UpdatedAt = updatedAt
};
var cancelResult = await _communicationService.CompleteWalkAsync(dto, accessToken, token);
if (cancelResult.Success)
{
if (cancelResult.Value)
{
success = true;
createDelta = false;
}
}
}
if (createDelta)
{
//TODO: Delta für Rating? Wie genau machen?
await _pushService.AddAsync(nameof(Walk), localWalk.Id, SyncOperation.Edit, localWalk).ConfigureAwait(false);
}
return success;
}
/// <summary>
/// Zahlungsstatus eines Walks setzen
/// </summary>
/// <param name="walkId">ID des Walks</param>
/// <param name="paymentStatus">Zahlungsstatus der gesetzt werden soll</param>
/// <param name="accessToken">Aktuelles Accesstoken</param>
/// <param name="token">CancellationToken</param>
/// <returns>true wenn erfolgreich, false sonst</returns>
public async Task<bool> SetPaymentStatusAsync(string walkId, PaymentStatus paymentStatus, string accessToken, CancellationToken token)
{
var success = false;
var localWalk = await Repository.FirstOrDefaultAsync(c => c.Id == walkId, false);
var updatedAt = DateTimeOffset.UtcNow;
if (localWalk != null)
{
localWalk.PaymentStatus = paymentStatus;
localWalk.UpdatedAt = updatedAt;
Repository.Update(localWalk);
await CommitAsync();
success = true;
}
//Jetzt am Server oder Delta erstellen
var createDelta = true;
var isConnected = await _communicationService.IsConnected();
if (isConnected)
{
var dto = new WalkPaymentStatusDto()
{
WalkId = walkId,
UpdatedAt = updatedAt,
PaymentStatus = (PaymentStatusDto)paymentStatus
};
var cancelResult = await _communicationService.SetWalkPaymentStatusAsync(dto, accessToken, token);
if (cancelResult.Success)
{
if (cancelResult.Value)
{
success = true;
createDelta = false;
}
}
}
if (createDelta)
{
await _pushService.AddAsync(nameof(Walk), localWalk.Id, SyncOperation.Edit, localWalk).ConfigureAwait(false);
}
return success;
}
/// <summary>
/// Prüfen ob ein Walk für einen DogWalker in einem Zeitraum gebucht werden kann
/// </summary>
/// <param name="dogWalkerId">Id des DogWalkers</param>
/// <param name="start">Start</param>
/// <param name="end">Ende</param>
/// <param name="accessToken">Aktuelles Accesstoken</param>
/// <param name="token">CancellationToken</param>
/// <returns>true wenn verfügbar, false sonst</returns>
public async Task<bool> IsWalkPossibleAsync(string dogWalkerId, DateTimeOffset start, DateTimeOffset end, string accessToken, CancellationToken token)
{
var isConnected = await _communicationService.IsConnected();
if (isConnected)
{
var query = new WalkPossibleDto()
{
DogWalkerId = dogWalkerId,
Start = start,
End = end
};
var queryResult = await _communicationService.IsWalkPossibleAsync(query, accessToken, token);
if (queryResult.Success)
return queryResult.Value;
}
return false;
}
/// <summary>
/// Anlegen eines Walks wenn DIREKT! buchen möglich ist.
/// Wird online versucht und erst dann lokal gespeichert
/// </summary>
/// <param name="requestDto">WalkCreateDto</param>
/// <param name="accessToken">Aktuelles Accesstoken</param>
/// <param name="token">CancellationToken</param>
/// <returns>Angelegter Walk oder null, wenn nicht erfolgreich</returns>
public async Task<CommunicationResult<Walk>> CreateWalkDirectAsync(WalkCreateDto requestDto, string accessToken, CancellationToken token)
{
var result = new CommunicationResult<Walk>() { Value = null, Success = false};
var isConnected = await _communicationService.IsConnected();
if (isConnected)
{
var createResult = await _communicationService.CreateWalkDirectAsync(requestDto, accessToken, token);
if (createResult.Success && createResult.Value.Status == CreateStatus.Success)
{
var walk = createResult.Value.Value;
if (walk != null)
{
Repository.Add(walk);
await CommitAsync();
result.Success = true;
result.Value = walk;
}
}
else
{
result.Success = false;
result.Value = null;
result.ErrorCode = createResult.ErrorCode;
result.ErrorMessage = createResult.ErrorMessage;
}
}
return result;
}
/// <summary>
/// Anlegen eines Walks als Anfrage
/// Wird online versucht und erst dann lokal gespeichert
/// </summary>
/// <param name="requestDto">WalkCreateDto</param>
/// <param name="accessToken">Aktuelles Accesstoken</param>
/// <param name="token">CancellationToken</param>
/// <returns>Angelegter Walk oder null, wenn nicht erfolgreich</returns>
public async Task<CommunicationResult<Walk>> CreateWalkRequestAsync(WalkCreateDto requestDto, string accessToken, CancellationToken token)
{
var result = new CommunicationResult<Walk>() { Value = null, Success = false };
var isConnected = await _communicationService.IsConnected();
if (isConnected)
{
var createResult = await _communicationService.CreateWalkRequestAsync(requestDto, accessToken, token);
if (createResult.Success && createResult.Value.Status == CreateStatus.Success)
{
var walk = createResult.Value.Value;
if (walk != null)
{
Repository.Add(walk);
await CommitAsync();
result.Success = true;
result.Value = walk;
}
}
else
{
result.Success = false;
result.Value = null;
result.ErrorCode = createResult.ErrorCode;
result.ErrorMessage = createResult.ErrorMessage;
}
}
return result;
}
/// <summary>
/// Akzeptieren eines Walks
/// </summary>
/// <param name="walkId">ID des Walks</param>
/// <param name="accessToken">Aktuelles Accesstoken</param>
/// <param name="token">CancellationToken</param>
/// <returns>true wenn erfolgreich, false sonst</returns>
public async Task<bool> AcceptAsync(string walkId, string accessToken, CancellationToken token)
{
var success = false;
var localWalk = await Repository.FirstOrDefaultAsync(c => c.Id == walkId, false);
var updatedAt = DateTimeOffset.UtcNow;
if (localWalk != null)
{
localWalk.Status = WalkStatus.Accepted;
localWalk.PaymentStatus = PaymentStatus.Pending;
localWalk.UpdatedAt = updatedAt;
if(localWalk.Price == 0)
localWalk.PaymentStatus = PaymentStatus.Paid;
Repository.Update(localWalk);
await CommitAsync();
success = true;
}
//Jetzt am Server oder Delta erstellen
var createDelta = true;
var isConnected = await _communicationService.IsConnected();
if (isConnected)
{
var dto = new WalkAcceptDto()
{
WalkId = walkId,
UpdatedAt = updatedAt
};
var cancelResult = await _communicationService.AcceptWalkAsync(dto, accessToken, token);
if (cancelResult.Success)
{
if (cancelResult.Value)
{
success = true;
createDelta = false;
}
}
}
if (createDelta)
{
await _pushService.AddAsync(nameof(Walk), localWalk.Id, SyncOperation.Edit, localWalk).ConfigureAwait(false);
}
return success;
}
/// <summary>
/// Ablehnen eines Walks
/// </summary>
/// <param name="walkId">ID des Walks</param>
/// <param name="declineReason">Grund der Ablehnung</param>
/// <param name="accessToken">Aktuelles Accesstoken</param>
/// <param name="token">CancellationToken</param>
/// <returns>true wenn erfolgreich, false sonst</returns>
public async Task<bool> DeclineAsync(string walkId, string declineReason, string accessToken, CancellationToken token)
{
var success = false;
var localWalk = await Repository.FirstOrDefaultAsync(c => c.Id == walkId, false);
var updatedAt = DateTimeOffset.UtcNow;
if (localWalk != null)
{
localWalk.Status = WalkStatus.Declined;
localWalk.UpdatedAt = updatedAt;
localWalk.DeclinedReason = declineReason;
Repository.Update(localWalk);
await CommitAsync();
success = true;
}
//Jetzt am Server oder Delta erstellen
var createDelta = true;
var isConnected = await _communicationService.IsConnected();
if (isConnected)
{
var dto = new WalkDeclineDto()
{
WalkId = walkId,
UpdatedAt = updatedAt,
DeclineReason = declineReason
};
var cancelResult = await _communicationService.DeclineWalkAsync(dto, accessToken, token);
if (cancelResult.Success)
{
if (cancelResult.Value)
{
success = true;
createDelta = false;
}
}
}
if (createDelta)
{
await _pushService.AddAsync(nameof(Walk), localWalk.Id, SyncOperation.Edit, localWalk).ConfigureAwait(false);
}
return success;
}
/// <summary>
/// Gibt zurück ob ein Walker Anfragen hat
/// </summary>
/// <param name="dogWalkerId">Id des Walkers</param>
/// <returns>true wenn ja, false sonst</returns>
public async Task<bool> HasRequestedAsync(string dogWalkerId)
{
var requested = await Repository.CountAsync(c => c.DogWalkerId == dogWalkerId && c.Status == WalkStatus.Requested && c.Deleted == false).ConfigureAwait(false);
return requested > 0;
}
/// <summary>
/// Gibt eine Liste von Walks zurück, welche gleich gestartet werden sollen
/// </summary>
/// <param name="appUserId">ID des AppUsers</param>
/// <param name="date">Datum für den Vergleich</param>
/// <returns>Liste von Walks die gestartet werden sollen</returns>
public async Task<List<Walk>> GetWalksToStartAsync(string appUserId, DateTimeOffset date)
{
var upperDate = date.AddHours(1);
var walks = await Repository.FindAsync(c => c.DogWalkerId == appUserId && c.Status == WalkStatus.Accepted && c.Start >= date && c.Start <= upperDate && c.Deleted == false).ConfigureAwait(false);
return walks.ToList();
}
/// <summary>
/// Gibt eine Liste von Walks zurück, welche beendet werden sollen
/// </summary>
/// <param name="appUserId">ID des AppUsers</param>
/// <param name="date">Datum für den Vergleich</param>
/// <returns>Liste von Walks die gestartet werden sollen</returns>
public async Task<List<Walk>> GetWalksToCompleteAsync(string appUserId, DateTimeOffset date)
{
var walks = await Repository.FindAsync(c => c.DogWalkerId == appUserId && (c.Status == WalkStatus.Accepted || c.Status == WalkStatus.Started) && c.End <= date && c.Deleted == false).ConfigureAwait(false);
return walks.ToList();
}
/// <summary>
/// Aktualisieren des Zahlungsstatus eines Walks in der lokalen DB
/// </summary>
/// <param name="walkId">Id des Wals</param>
/// <param name="paymentStatus">Zu setzender Zahlungsstatus</param>
/// <param name="updatedAt">Datum Aktualisierung</param>
/// <returns>Walk oder null, wenn nicht gefunden</returns>
public async Task<Walk> SetPaymentStatusLocalAsync(string walkId, PaymentStatus paymentStatus, DateTimeOffset updatedAt)
{
var localWalk = await Repository.FirstOrDefaultAsync(c => c.Id == walkId, false);
if (localWalk != null)
{
localWalk.PaymentStatus = paymentStatus;
localWalk.UpdatedAt = updatedAt;
Repository.Update(localWalk);
await CommitAsync();
await _pullService.AddOrUpddateAsync(nameof(Walk), updatedAt).ConfigureAwait(false);
return localWalk;
}
return null;
}
/// <summary>
/// Bestätigen eines Walks. Löst die Bezahlung für einen Walker aus. Geht nur Online!
/// </summary>
/// <param name="appUserId">Id des Hundebesitzers</param>
/// <param name="walkId">Id des Walks</param>
/// <param name="accessToken">Aktuelles Accesstoken</param>
/// <param name="token">CancellationToken</param>
/// <returns>CommunicationResult mit aktualisierten Walk</returns>
public async Task<CommunicationResult<Walk>> ConfirmAsync(string appUserId, string walkId, string accessToken, CancellationToken token)
{
var result = new CommunicationResult<Walk>();
var hasConnection = await _communicationService.IsConnected();
if (hasConnection)
{
var model = new WalkConfirmDto()
{
AppUserId = appUserId,
WalkId = walkId
};
var serverResult = await _communicationService.ConfirmWalkAsync(model, accessToken, token);
if (serverResult.Success && serverResult.Value != null)
{
//jetzt auch lokal die Änderung speichern
var localWalk = await Repository.FirstOrDefaultAsync(c => c.Id == walkId, false);
if (localWalk != null)
{
localWalk.Status = serverResult.Value.Status;
localWalk.Confirmed = serverResult.Value.Confirmed;
localWalk.PaymentStatus = serverResult.Value.PaymentStatus;
localWalk.UpdatedAt = serverResult.Value.UpdatedAt;
Repository.Update(localWalk);
await CommitAsync();
await _pullService.AddOrUpddateAsync(nameof(Walk), localWalk.UpdatedAt);
}
}
return serverResult;
}
else
{
result.Success = false;
result.ErrorCode = CommunicationErrors.ServerNoConnection;
result.ErrorMessage = Errors.Server_NoConnection;
}
return result;
}
/// <summary>
/// Bestätigen eines Walks mit Rating. Löst die Bezahlung für einen Walker aus. Geht nur Online!
/// </summary>
/// <param name="appUserId">Id des Hundebesitzers</param>
/// <param name="walkId">Id des Walks</param>
/// <param name="ratingPoints">Punkte für das Rating</param>
/// <param name="ratingInfo">Anmerkungen zum Rating</param>
/// <param name="accessToken">Aktuelles Accesstoken</param>
/// <param name="token">CancellationToken</param>
/// <returns>CommunicationResult mit aktualisierten Walk</returns>
public async Task<CommunicationResult<Walk>> ConfirmWithRatingAsync(string appUserId, string walkId, decimal ratingPoints, string ratingInfo, string accessToken, CancellationToken token)
{
var result = new CommunicationResult<Walk>();
var hasConnection = await _communicationService.IsConnected();
if (hasConnection)
{
var model = new WalkConfirmWithRatingDto()
{
AppUserId = appUserId,
WalkId = walkId,
RatingPoints = ratingPoints,
RatingInfo = ratingInfo
};
var serverResult = await _communicationService.ConfirmWalkWithRatingAsync(model, accessToken, token);
if (serverResult.Success && serverResult.Value != null)
{
//jetzt auch lokal die Änderung speichern
var localWalk = await Repository.FirstOrDefaultAsync(c => c.Id == walkId, false);
if (localWalk != null)
{
localWalk.Status = serverResult.Value.Status;
localWalk.Confirmed = serverResult.Value.Confirmed;
localWalk.PaymentStatus = serverResult.Value.PaymentStatus;
localWalk.UpdatedAt = serverResult.Value.UpdatedAt;
Repository.Update(localWalk);
await CommitAsync();
await _pullService.AddOrUpddateAsync(nameof(Walk), localWalk.UpdatedAt);
}
}
return serverResult;
}
else
{
result.Success = false;
result.ErrorCode = CommunicationErrors.ServerNoConnection;
result.ErrorMessage = Errors.Server_NoConnection;
}
return result;
}
/// <summary>
/// Reklamieren eines Walks
/// </summary>
/// <param name="walkId">ID des Walks</param>
/// <param name="type">Typ der Reklamation</param>
/// <param name="complainReason">Grund der Reklamation als Text</param>
/// <param name="accessToken">Aktuelles Accesstoken</param>
/// <param name="token">CancellationToken</param>
/// <returns>true wenn erfolgreich, false sonst</returns>
public async Task<CommunicationResult<bool>> ComplainAsync(string walkId, WalkComplaintType type, string complainReason, string accessToken, CancellationToken token)
{
var result = new CommunicationResult<bool>();
var hasConnection = await _communicationService.IsConnected();
if (hasConnection)
{
var model = new WalkComplaintCreateDto()
{
WalkId = walkId,
Type = type.ToDto(),
Message = complainReason
};
var serverResult = await _communicationService.ComplainWalkAsync(model, accessToken, token);
if (serverResult.Success && serverResult.Value != null)
{
//jetzt auch lokal die Änderung speichern
var localWalk = await Repository.FirstOrDefaultAsync(c => c.Id == walkId, false);
if (localWalk != null)
{
localWalk.Status = serverResult.Value.Status;
localWalk.Complained = serverResult.Value.Complained;
localWalk.ComplainReason = serverResult.Value.ComplainReason;
localWalk.UpdatedAt = serverResult.Value.UpdatedAt;
Repository.Update(localWalk);
await CommitAsync();
await _pullService.AddOrUpddateAsync(nameof(Walk), localWalk.UpdatedAt);
result.Success = true;
result.Value = true;
}
}
}
else
{
result.Success = false;
result.ErrorCode = CommunicationErrors.ServerNoConnection;
result.ErrorMessage = Errors.Server_NoConnection;
}
return result;
}
/// <summary>
/// Holen einer Reklamation zu einem Walk
/// </summary>
/// <param name="walkId">ID des Walks</param>
/// <param name="accessToken">Aktuelles Accesstoken</param>
/// <param name="token">CancellationToken</param>
/// <returns>CommunicationResult</returns>
public async Task<CommunicationResult<WalkComplaint>> GetWalkComplaintAsync(string walkId, string accessToken, CancellationToken token)
{
var result = new CommunicationResult<WalkComplaint>();
result.Success = false;
var isConnected = await _communicationService.IsConnected();
if (isConnected)
{
var queryResult = await _communicationService.GetWalkComplaintAsync(walkId, accessToken, token);
if (queryResult.Success)
{
result.Success = true;
result.Value = queryResult.Value;
return result;
}
}
else
{
result.Success = false;
result.ErrorCode = CommunicationErrors.ServerNoConnection;
result.ErrorMessage = Errors.Server_NoConnection;
}
return result;
}
#region Pull-Push Implementation
/// <summary>
/// Holen der letzten Daten vom Server und Synchronisieren mit den lokalen Daten
/// </summary>
/// <param name="language">Sprache</param>
/// <param name="accessToken">Aktuelles Accesstoken</param>
/// <param name="token">CancellationToken</param>
/// <returns>Task</returns>
public async Task<SyncResult<Walk>> PullAsync(string language, string accessToken, CancellationToken token)
{
var result = new SyncResult<Walk>();
var isConnected = await _communicationService.IsConnected();
if (isConnected)
{
var user = await _appUserRepository.FirstOrDefaultAsync(c => c.Id != "", false).ConfigureAwait(false);
//Zuerst lezte Aktivität holen...
DateTimeOffset? lastUpdate = null;
var lastSyncInfo = await _pullService.GetAsync(nameof(Walk));
if (lastSyncInfo != null)
lastUpdate = lastSyncInfo.LastUpdate;
var requestResult = await _communicationService.GetWalksForSyncAsync(user.Id, lastUpdate, accessToken, token);
if (requestResult.Success)
{
result = await HandleChangesAsync(requestResult.Value);
if (result.LastUpdate != null)
await _pullService.AddOrUpddateAsync(nameof(Walk), result.LastUpdate.Value).ConfigureAwait(false);
}
result.LastUpdate ??= lastUpdate;
}
return result;
}
/// <summary>
/// Holen der Daten vom lokalen Speicher die noch nicht synchronisiert wurden und senden an den Server
/// </summary>
/// <param name="accessToken">Aktuelles Accesstoken</param>
/// <param name="token">CancellationToken</param>
/// <returns>Task</returns>
public async Task<SyncResult<Walk>> PushAsync(string accessToken, CancellationToken token)
{
var result = new SyncResult<Walk>();
if (await _pushService.HasOpenAsync(nameof(Walk)) > 0)
{
var deltas = await _pushService.GetAllAsync(nameof(Walk));
if (deltas.Any())
{
var user = await _appUserRepository.FirstOrDefaultAsync(c => c.Id != "", false).ConfigureAwait(false);
deltas = deltas.OrderBy(c => c.DateTime).ToList();
var isConnected = await _communicationService.IsConnected();
if (!isConnected) return result;
foreach (var syncInfoPush in deltas)
{
try
{
if (!string.IsNullOrWhiteSpace(syncInfoPush.Value))
{
var request = JsonSerializer.Deserialize<Walk>(syncInfoPush.Value, new JsonSerializerOptions(JsonSerializerDefaults.Web));
if (syncInfoPush.Operation == SyncOperation.Create)
{
var createDto = request.ToDto();
var createResult = await _communicationService.CreateWalkAsync(createDto, accessToken, token);
if (createResult.Success && createResult.Value.Status != CreateStatus.Error)
{
await _pushService.RemoveAsync(syncInfoPush.Id).ConfigureAwait(false);
}
//TODO: Was tun wenn Fehler?
}
else if (syncInfoPush.Operation == SyncOperation.Edit)
{
var updateDto = request.ToDto();
var updateResult = await _communicationService.UpdateWalkAsync(updateDto, accessToken, token);
if (updateResult.Success && updateResult.Value)
await _pushService.RemoveAsync(syncInfoPush.Id).ConfigureAwait(false);
//TODO: Was tun wenn Fehler?
}
else
{
var deleteDto = request.ToDto();
var deleteResult = await _communicationService.DeleteWalkAsync(deleteDto, user.Id, accessToken, token);
if (deleteResult.Success && deleteResult.Value)
await _pushService.RemoveAsync(syncInfoPush.Id).ConfigureAwait(false);
//TODO: Was tun wenn Fehler?
}
}
else
{
await _pushService.RemoveAsync(syncInfoPush.Id).ConfigureAwait(false);
}
}
catch (Exception ex)
{
System.Diagnostics.Debug.WriteLine(ex.Message);
await _pushService.RemoveAsync(syncInfoPush.Id).ConfigureAwait(false);
}
}
//Else ist nichts tun, konnte nicht übertragen werden.
}
}
return result;
}
#endregion
#region Private
/// <summary>
/// Behandeln der Liste von öffentlichern Anfragen wenn welche vom Online-Store geholt werden.
/// </summary>
/// <param name="walks">Liste der anfragen</param>
/// <returns>Task</returns>
private async Task<SyncResult<Walk>> HandleChangesAsync(List<Walk> walks)
{
var result = new SyncResult<Walk>();
//Je Rasse durchgehen ob was gemacht werden soll
foreach (var walk in walks)
{
var localWalk = await Repository.FirstOrDefaultAsync(c => c.Id == walk.Id, false);
if (localWalk != null && localWalk.UpdatedAt < walk.UpdatedAt)
{
if (localWalk.UpdatedAt >= walk.UpdatedAt)
{
if (result.LastUpdate == null || result.LastUpdate < localWalk.UpdatedAt)
result.LastUpdate = localWalk.UpdatedAt;
continue;
}
var deleted = localWalk.Deleted == false && walk.Deleted;
localWalk.Version = walk.Version;
localWalk.UpdatedAt = walk.UpdatedAt;
localWalk.Deleted = walk.Deleted;
localWalk.Type = walk.Type;
localWalk.ServiceType = walk.ServiceType;
localWalk.DogWalkerId = walk.DogWalkerId;
localWalk.DogOwnerId = walk.DogOwnerId;
localWalk.PublicWalkRequestId = walk.PublicWalkRequestId;
localWalk.DogsJson = walk.DogsJson;
localWalk.DogCount = walk.DogCount;
localWalk.Start = walk.Start;
localWalk.End = walk.End;
localWalk.PickupAddress = walk.PickupAddress;
localWalk.PickupAddressLat = walk.PickupAddressLat;
localWalk.PickupAddressLng = walk.PickupAddressLng;
localWalk.ReturnAddress = walk.ReturnAddress;
localWalk.ReturnAddressLat = walk.ReturnAddressLat;
localWalk.ReturnAddressLng = walk.ReturnAddressLng;
localWalk.Price = walk.Price;
localWalk.Info = walk.Info;
localWalk.Status = walk.Status;
localWalk.Started = walk.Started;
localWalk.Completed = walk.Completed;
localWalk.Confirmed = walk.Confirmed;
localWalk.Complained = walk.Complained;
localWalk.ComplainReason = walk.ComplainReason;
localWalk.DeclinedReason = walk.DeclinedReason;
localWalk.CancelledReason = walk.CancelledReason;
localWalk.CancelledBy = walk.CancelledBy;
localWalk.CompletedInfo = walk.CompletedInfo;
localWalk.Defactation = walk.Defactation;
localWalk.PaymentStatus = walk.PaymentStatus;
localWalk.Created = walk.Created;
if (result.LastUpdate == null || result.LastUpdate < localWalk.UpdatedAt)
result.LastUpdate = localWalk.UpdatedAt;
if (!deleted)
result.Updated.Add(localWalk);
else
result.Deleted.Add(localWalk);
Repository.Update(localWalk);
}
if (localWalk == null)
{
localWalk = new Walk()
{
Id = walk.Id,
Version = walk.Version,
UpdatedAt = walk.UpdatedAt,
Deleted = walk.Deleted,
Type = walk.Type,
ServiceType = walk.ServiceType,
DogWalkerId = walk.DogWalkerId,
DogOwnerId = walk.DogOwnerId,
PublicWalkRequestId = walk.PublicWalkRequestId,
DogsJson = walk.DogsJson,
DogCount = walk.DogCount,
Start = walk.Start,
End = walk.End,
PickupAddress = walk.PickupAddress,
PickupAddressLat = walk.PickupAddressLat,
PickupAddressLng = walk.PickupAddressLng,
ReturnAddress = walk.ReturnAddress,
ReturnAddressLat = walk.ReturnAddressLat,
ReturnAddressLng = walk.ReturnAddressLng,
Price = walk.Price,
Info = walk.Info,
Status = walk.Status,
Started = walk.Started,
Completed = walk.Completed,
Confirmed = walk.Confirmed,
Complained = walk.Complained,
ComplainReason = walk.ComplainReason,
DeclinedReason = walk.DeclinedReason,
CancelledReason = walk.CancelledReason,
CancelledBy = walk.CancelledBy,
CompletedInfo = walk.CompletedInfo,
Defactation = walk.Defactation,
PaymentStatus = walk.PaymentStatus,
Created = walk.Created
};
Repository.Add(localWalk);
if (result.LastUpdate == null || result.LastUpdate < localWalk.UpdatedAt)
result.LastUpdate = localWalk.UpdatedAt;
result.Added.Add(localWalk);
}
}
if (result.HasChanges)
{
try
{
await CommitAsync().ConfigureAwait(false);
}
catch (Exception ex)
{
var err = ex.Message;
}
}
return result;
}
#endregion
}
}