Significant updates to WalkService.cs for improved fee handling and voucher processing. Introduced API version 3 in ApiAccountController.cs with new user registration and external login endpoints, supporting Google and Apple. Added functionality for setting user types without creating MangoPay users.
876 lines
48 KiB
C#
876 lines
48 KiB
C#
using gehGassi.Core.Interfaces;
|
|
using gehGassi.Domain.Walks;
|
|
using Microsoft.EntityFrameworkCore;
|
|
using NetTopologySuite.Geometries;
|
|
using NetTopologySuite;
|
|
using System;
|
|
using System.Collections.Generic;
|
|
using System.Linq;
|
|
using System.Text;
|
|
using System.Threading.Tasks;
|
|
using gehGassi.Common.Extensions;
|
|
using gehGassi.Domain.Common;
|
|
using Microsoft.Data.SqlClient;
|
|
using gehGassi.Domain.Dogs;
|
|
using gehGassi.Domain.Payment;
|
|
using Azure;
|
|
using gehGassi.Dto.Messages;
|
|
|
|
namespace gehGassi.Core.Services
|
|
{
|
|
/// <summary>
|
|
/// Service der die Verwaltung von Walks ermöglicht
|
|
/// </summary>
|
|
public class WalkService : ServiceBase<Walk>, IWalkService
|
|
{
|
|
private readonly IServiceProvider _serviceProvider;
|
|
private readonly IRepository<WalkWithNames> _namesRepository;
|
|
private readonly IRepository<PublicWalkRequest> _publicWalkRequestRepository;
|
|
private readonly IRepository<PublicWalkResponse> _publicWalkResponseRepository;
|
|
|
|
/// <summary>
|
|
/// Erstellt eine Instanz
|
|
/// </summary>
|
|
/// <param name="unitOfWork">Instanz eines IUnitOfWork</param>
|
|
/// <param name="serviceProvider">Instanz eines IServiceProvider</param>
|
|
public WalkService(IUnitOfWork unitOfWork, IServiceProvider serviceProvider) : base(unitOfWork)
|
|
{
|
|
_serviceProvider = serviceProvider;
|
|
_namesRepository = unitOfWork.GetRepository<WalkWithNames>();
|
|
_publicWalkRequestRepository = unitOfWork.GetRepository<PublicWalkRequest>();
|
|
_publicWalkResponseRepository = unitOfWork.GetRepository<PublicWalkResponse>();
|
|
}
|
|
|
|
/// <summary>
|
|
/// Erstellen eines Walks
|
|
/// </summary>
|
|
/// <returns>Walk</returns>
|
|
public Walk Create()
|
|
{
|
|
var walk = new Walk()
|
|
{
|
|
Id = Guid.NewGuid().ToString("N"),
|
|
PaymentType = WalkPaymentType.MangoPay,
|
|
Created = DateTimeOffset.UtcNow
|
|
};
|
|
return walk;
|
|
}
|
|
|
|
/// <summary>
|
|
/// Gibt eine Liste der Walks eines Benutzers zurück. Kann Owner und Walker sein
|
|
/// </summary>
|
|
/// <param name="appUserId">Id des AppUsers</param>
|
|
/// <param name="lastUpdate">Letztes Update</param>
|
|
/// <returns>Liste der öffentlichen Anfragen</returns>
|
|
public async Task<List<Walk>> GetForSyncAppAsync(string appUserId, DateTimeOffset? lastUpdate)
|
|
{
|
|
var query = Repository.Query(c => c.DogOwnerId == appUserId || c.DogWalkerId == appUserId);
|
|
|
|
if (lastUpdate.HasValue)
|
|
query = query.Where(c => c.UpdatedAt > lastUpdate);
|
|
|
|
return await query.ToListAsync().ConfigureAwait(false);
|
|
}
|
|
|
|
/// <summary>
|
|
/// Gibt eine gefilterte Liste von Walks zurück
|
|
/// </summary>
|
|
/// <param name="filter">Filterbegriff der in bestimmten Feldern gesucht wird</param>
|
|
/// <param name="includeDeleted">Sollen gelöschte inkludiert werden?</param>
|
|
/// <returns>Liste betroffener öffentlicher Anfragen</returns>
|
|
public IQueryable<WalkWithNames> FilterWithNames(string filter, bool includeDeleted)
|
|
{
|
|
var baseQuery = _namesRepository.QueryStoredProcedure("SELECT * FROM tv_WalksWithNames()", c => c.DogOwnerName.Contains(filter) || c.DogWalkerName.Contains(filter) || c.PickupAddress_City.Contains(filter));
|
|
|
|
if (!includeDeleted)
|
|
baseQuery = baseQuery.Where(c => c.Deleted == false);
|
|
|
|
return baseQuery;
|
|
}
|
|
|
|
/// <summary>
|
|
/// Gibt eine Liste von Walks mit Namen aufgelöst zurück
|
|
/// </summary>
|
|
/// <param name="dogWalkerId">Id des Dogwalkers oder leer wenn nicht für DogWalker</param>
|
|
/// <param name="dogOwnerId">Id des DogOwners oder leer wenn nicht für DogOwner</param>
|
|
/// <param name="date">Datum ab dem gesucht werden soll oder NULL wenn 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: nach HundeID filtern</param>
|
|
/// <param name="walkerFilter">Optional: nach Walkername filtern</param>
|
|
/// <param name="ownerFilter">Optional: nach Ownername filtern</param>
|
|
/// <param name="ignoreCancelled">Stornierte Ignorieren</param>
|
|
/// <param name="forNextWalk">Sollen nur Walks für den nächsten Walk selektiert werden? Dann nur Angenommene oder Laufende</param>
|
|
/// <param name="ignoreRequested">Sollen Walks die noch eine Anfrage sind, ohne Akzeptiert oder Agelehnt ignorniert werden?</param>
|
|
/// <param name="ignoreDeclined">Sollen abgelehnte Walks ignoriert werden?</param>
|
|
/// <param name="sortList">Optional: Liste der sortierung</param>
|
|
/// <param name="lat">Optional: Breitengrad</param>
|
|
/// <param name="lng">Optional: Längengrad</param>
|
|
/// <param name="skip">Datensätze auslassen</param>
|
|
/// <param name="take">Datensätze nehmen</param>
|
|
/// <returns>Liste gefudene Walks</returns>
|
|
public async Task<(int total, List<WalkWithNames> list)> GetWithNamesAsync(string dogWalkerId, string dogOwnerId, DateTimeOffset? date, WalkStatus? status, WalkServiceType? serviceType, PaymentStatus? paymentStatus, string dogFilter, string walkerFilter, string ownerFilter, bool ignoreCancelled, bool forNextWalk, bool ignoreRequested, bool ignoreDeclined, List<DynamicSortOrder> sortList, double lat, double lng, int skip, int take)
|
|
{
|
|
var geometryFactory = NtsGeometryServices.Instance.CreateGeometryFactory(srid: 4326);
|
|
var location = geometryFactory.CreatePoint(new Coordinate(lng, lat));
|
|
|
|
var baseQuery = _namesRepository.QueryStoredProcedure("SELECT * FROM tv_WalksWithNames()", c => c.Deleted == false);
|
|
|
|
if(!string.IsNullOrWhiteSpace(dogWalkerId))
|
|
baseQuery = baseQuery.Where(c => c.DogWalkerId == dogWalkerId);
|
|
if (!string.IsNullOrWhiteSpace(dogOwnerId))
|
|
baseQuery = baseQuery.Where(c => c.DogOwnerId == dogOwnerId);
|
|
if(date.HasValue)
|
|
baseQuery = baseQuery.Where(c => c.Start >= date);
|
|
if (status.HasValue)
|
|
{
|
|
baseQuery = baseQuery.Where(c => c.Status == status);
|
|
}
|
|
else
|
|
{
|
|
if(ignoreCancelled)
|
|
baseQuery = baseQuery.Where(c => c.Status != WalkStatus.Cancelled);
|
|
if (forNextWalk)
|
|
{
|
|
baseQuery = baseQuery.Where(c => c.Status == WalkStatus.Accepted || c.Status == WalkStatus.Started);
|
|
}
|
|
if (ignoreRequested)
|
|
baseQuery = baseQuery.Where(c => c.Status != WalkStatus.Requested);
|
|
if (ignoreDeclined)
|
|
baseQuery = baseQuery.Where(c => c.Status != WalkStatus.Declined);
|
|
}
|
|
if (serviceType.HasValue)
|
|
baseQuery = baseQuery.Where(c => c.ServiceType == serviceType);
|
|
if (paymentStatus.HasValue)
|
|
baseQuery = baseQuery.Where(c => c.PaymentStatus == paymentStatus);
|
|
if (!string.IsNullOrWhiteSpace(dogFilter))
|
|
baseQuery = baseQuery.Where(c => c.DogsJson.Contains(dogFilter));
|
|
if (!string.IsNullOrWhiteSpace(walkerFilter))
|
|
baseQuery = baseQuery.Where(c => c.DogWalkerName.Contains(walkerFilter));
|
|
if (!string.IsNullOrWhiteSpace(ownerFilter))
|
|
baseQuery = baseQuery.Where(c => c.DogOwnerName.Contains(ownerFilter));
|
|
|
|
var total = await baseQuery.CountAsync().ConfigureAwait(false);
|
|
|
|
if (sortList.Any())
|
|
{
|
|
var isFirst = true;
|
|
var orderedBaseQuery = baseQuery.SpecialOrderBy(sortList.First().Property, sortList.First().SortDirection); ;
|
|
foreach (var sortOrder in sortList)
|
|
{
|
|
if (isFirst)
|
|
{
|
|
isFirst = false;
|
|
continue;
|
|
}
|
|
else
|
|
{
|
|
orderedBaseQuery = orderedBaseQuery.SpecialThenBy(sortOrder.Property, sortOrder.SortDirection);
|
|
}
|
|
}
|
|
var list = await orderedBaseQuery.ThenBy(c => c.PickupLocation.Distance(location)).Skip(skip).Take(take).ToListAsync().ConfigureAwait(false);
|
|
return (total, list);
|
|
}
|
|
else
|
|
{
|
|
var list = await baseQuery.OrderBy(c => c.Start).ThenBy(c => c.PickupLocation.Distance(location)).Skip(skip).Take(take).ToListAsync().ConfigureAwait(false);
|
|
return (total, list);
|
|
}
|
|
}
|
|
|
|
/// <summary>
|
|
/// Gibt eine Liste von Walks mit Namen aufgelöst zurück für Walker
|
|
/// Sonderfall hier ist, dass keine Walks mit einem PaymentStatus unter Authorized zurückgibt
|
|
/// </summary>
|
|
/// <param name="dogWalkerId">Id des Dogwalkers oder leer wenn nicht für DogWalker</param>
|
|
/// <param name="dogOwnerId">Id des DogOwners oder leer wenn nicht für DogOwner</param>
|
|
/// <param name="date">Datum ab dem gesucht werden soll oder NULL wenn 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: nach HundeID filtern</param>
|
|
/// <param name="walkerFilter">Optional: nach Walkername filtern</param>
|
|
/// <param name="ownerFilter">Optional: nach Ownername filtern</param>
|
|
/// <param name="ignoreCancelled">Stornierte Ignorieren</param>
|
|
/// <param name="forNextWalk">Sollen nur Walks für den nächsten Walk selektiert werden? Dann nur Angenommene oder Laufende</param>
|
|
/// <param name="ignoreRequested">Sollen Walks die noch eine Anfrage sind, ohne Akzeptiert oder Agelehnt ignorniert werden?</param>
|
|
/// <param name="ignoreDeclined">Sollen abgelehnte Walks ignoriert werden?</param>
|
|
/// <param name="sortList">Optional: Liste der sortierung</param>
|
|
/// <param name="lat">Optional: Breitengrad</param>
|
|
/// <param name="lng">Optional: Längengrad</param>
|
|
/// <param name="skip">Datensätze auslassen</param>
|
|
/// <param name="take">Datensätze nehmen</param>
|
|
/// <returns>Liste gefudene Walks</returns>
|
|
public async Task<(int total, List<WalkWithNames> list)> GetWithNamesForWalkerAsync(string dogWalkerId, string dogOwnerId, DateTimeOffset? date, WalkStatus? status, WalkServiceType? serviceType, PaymentStatus? paymentStatus, string dogFilter, string walkerFilter, string ownerFilter, bool ignoreCancelled, bool forNextWalk, bool ignoreRequested, bool ignoreDeclined, List<DynamicSortOrder> sortList, double lat, double lng, int skip, int take)
|
|
{
|
|
var geometryFactory = NtsGeometryServices.Instance.CreateGeometryFactory(srid: 4326);
|
|
var location = geometryFactory.CreatePoint(new Coordinate(lng, lat));
|
|
|
|
var baseQuery = _namesRepository.QueryStoredProcedure("SELECT * FROM tv_WalksWithNames()", c => c.Deleted == false);
|
|
|
|
if (!string.IsNullOrWhiteSpace(dogWalkerId))
|
|
baseQuery = baseQuery.Where(c => c.DogWalkerId == dogWalkerId);
|
|
if (!string.IsNullOrWhiteSpace(dogOwnerId))
|
|
baseQuery = baseQuery.Where(c => c.DogOwnerId == dogOwnerId);
|
|
if (date.HasValue)
|
|
baseQuery = baseQuery.Where(c => c.Start >= date);
|
|
if (status.HasValue)
|
|
{
|
|
baseQuery = baseQuery.Where(c => c.Status == status);
|
|
}
|
|
else
|
|
{
|
|
if (ignoreCancelled)
|
|
baseQuery = baseQuery.Where(c => c.Status != WalkStatus.Cancelled);
|
|
if (forNextWalk)
|
|
{
|
|
baseQuery = baseQuery.Where(c => c.Status == WalkStatus.Accepted || c.Status == WalkStatus.Started);
|
|
}
|
|
if (ignoreRequested)
|
|
baseQuery = baseQuery.Where(c => c.Status != WalkStatus.Requested);
|
|
if (ignoreDeclined)
|
|
baseQuery = baseQuery.Where(c => c.Status != WalkStatus.Declined);
|
|
}
|
|
if (serviceType.HasValue)
|
|
baseQuery = baseQuery.Where(c => c.ServiceType == serviceType);
|
|
|
|
if (paymentStatus.HasValue)
|
|
baseQuery = baseQuery.Where(c => c.PaymentStatus == paymentStatus && c.PaymentStatus >= PaymentStatus.Authorized);
|
|
else
|
|
baseQuery = baseQuery.Where(c => c.PaymentStatus >= PaymentStatus.Authorized || (c.PaymentStatus == PaymentStatus.None && (c.Status == WalkStatus.Requested || c.Status == WalkStatus.Declined)));
|
|
|
|
if (!string.IsNullOrWhiteSpace(dogFilter))
|
|
baseQuery = baseQuery.Where(c => c.DogsJson.Contains(dogFilter));
|
|
if (!string.IsNullOrWhiteSpace(walkerFilter))
|
|
baseQuery = baseQuery.Where(c => c.DogWalkerName.Contains(walkerFilter));
|
|
if (!string.IsNullOrWhiteSpace(ownerFilter))
|
|
baseQuery = baseQuery.Where(c => c.DogOwnerName.Contains(ownerFilter));
|
|
|
|
var total = await baseQuery.CountAsync().ConfigureAwait(false);
|
|
|
|
if (sortList.Any())
|
|
{
|
|
var isFirst = true;
|
|
var orderedBaseQuery = baseQuery.SpecialOrderBy(sortList.First().Property, sortList.First().SortDirection); ;
|
|
foreach (var sortOrder in sortList)
|
|
{
|
|
if (isFirst)
|
|
{
|
|
isFirst = false;
|
|
continue;
|
|
}
|
|
else
|
|
{
|
|
orderedBaseQuery = orderedBaseQuery.SpecialThenBy(sortOrder.Property, sortOrder.SortDirection);
|
|
}
|
|
}
|
|
var list = await orderedBaseQuery.ThenBy(c => c.PickupLocation.Distance(location)).Skip(skip).Take(take).ToListAsync().ConfigureAwait(false);
|
|
return (total, list);
|
|
}
|
|
else
|
|
{
|
|
var list = await baseQuery.OrderBy(c => c.Start).ThenBy(c => c.PickupLocation.Distance(location)).Skip(skip).Take(take).ToListAsync().ConfigureAwait(false);
|
|
return (total, list);
|
|
}
|
|
}
|
|
|
|
/// <summary>
|
|
/// Gibt eine Liste von Walks mit Namen aufgelöst zurück für Hundebesitzer die anstehen, laufen, nicht abgeschlossen sind, nicht gestartet wurden oder zu bezahlen sind
|
|
/// </summary>
|
|
/// <param name="dogOwnerId">Id des Hundebesitzers</param>
|
|
/// <param name="date">Datum ab dem gesucht werden soll oder NULL wenn alle</param>
|
|
/// <param name="skip">Datensätze auslassen</param>
|
|
/// <param name="take">Datensätze nehmen</param>
|
|
/// <returns>Liste gefudene Walks</returns>
|
|
public async Task<(int total, List<WalkWithNames> list)> GetNextWithNamesForOwnerAsync(string dogOwnerId, DateTimeOffset date, int skip, int take)
|
|
{
|
|
var total = 0;
|
|
var list = new List<WalkWithNames>();
|
|
|
|
//1. Aktuell laufende Walks
|
|
var baseQuery = _namesRepository.QueryStoredProcedure("SELECT * FROM tv_WalksWithNames()", c => c.DogOwnerId == dogOwnerId && c.Deleted == false && c.Status == WalkStatus.Started);
|
|
//baseQuery = baseQuery.Where(c => c.Start <= date && c.End >= date);
|
|
//Anpassung, Walks auch dann anzeigen, wenn gestartet aber das Startdatum noch nicht erreicht ist
|
|
//baseQuery = baseQuery.Where(c => c.Start <= date && c.End >= date);
|
|
baseQuery = baseQuery.Where(c => c.End >= date);
|
|
list.AddRange(await baseQuery.OrderBy(c => c.Start).ToListAsync().ConfigureAwait(false));
|
|
|
|
//2. Nicht gestartete Walks
|
|
baseQuery = _namesRepository.QueryStoredProcedure("SELECT * FROM tv_WalksWithNames()", c => c.DogOwnerId == dogOwnerId && c.Deleted == false && c.Status == WalkStatus.Accepted && c.PaymentStatus == PaymentStatus.Authorized);
|
|
baseQuery = baseQuery.Where(c => c.Start <= date && c.End >= date);
|
|
list.AddRange(await baseQuery.OrderBy(c => c.Start).ToListAsync().ConfigureAwait(false));
|
|
|
|
//3. Zu bezahlende Walks
|
|
baseQuery = _namesRepository.QueryStoredProcedure("SELECT * FROM tv_WalksWithNames()", c => c.DogOwnerId == dogOwnerId && c.Deleted == false && c.Status == WalkStatus.Accepted && c.PaymentStatus == PaymentStatus.Pending);
|
|
list.AddRange(await baseQuery.OrderBy(c => c.Start).ToListAsync().ConfigureAwait(false));
|
|
|
|
//4. Nicht abgeschlossene Walks
|
|
baseQuery = _namesRepository.QueryStoredProcedure("SELECT * FROM tv_WalksWithNames()", c => c.DogOwnerId == dogOwnerId && c.Deleted == false && (c.Status == WalkStatus.Accepted || c.Status == WalkStatus.Started) && c.PaymentStatus == PaymentStatus.Authorized);
|
|
baseQuery = baseQuery.Where(c => c.End <= date);
|
|
list.AddRange(await baseQuery.OrderBy(c => c.Start).ToListAsync().ConfigureAwait(false));
|
|
|
|
//5. Nicht bestätigte Walks
|
|
baseQuery = _namesRepository.QueryStoredProcedure("SELECT * FROM tv_WalksWithNames()", c => c.DogOwnerId == dogOwnerId && c.Deleted == false && c.Status == WalkStatus.Completed && c.PaymentStatus == PaymentStatus.Authorized);
|
|
baseQuery = baseQuery.Where(c => c.End <= date);
|
|
list.AddRange(await baseQuery.OrderBy(c => c.Start).ToListAsync().ConfigureAwait(false));
|
|
|
|
//6. Nächster anstehender Walk
|
|
baseQuery = _namesRepository.QueryStoredProcedure("SELECT * FROM tv_WalksWithNames()", c => c.DogOwnerId == dogOwnerId && c.Deleted == false && c.Status == WalkStatus.Accepted && c.PaymentStatus == PaymentStatus.Authorized);
|
|
baseQuery = baseQuery.Where(c => c.Start >= date).OrderBy(c => c.Start);
|
|
var nextWaks = (await baseQuery.ToListAsync().ConfigureAwait(false)).Skip(0).Take(3);
|
|
if(nextWaks.Any())
|
|
list.AddRange(nextWaks);
|
|
|
|
total = list.Count;
|
|
list = list.Skip(skip).Take(take).ToList();
|
|
|
|
return (total, list);
|
|
}
|
|
|
|
/// <summary>
|
|
/// Gibt eine Liste von Walks mit Namen aufgelöst zurück für Walker die anstehen, laufen, nicht abgeschlossen sind oder nicht gestartet wurden
|
|
/// </summary>
|
|
/// <param name="dogWalkerId">Id des Walkers</param>
|
|
/// <param name="date">Datum ab dem gesucht werden soll oder NULL wenn alle</param>
|
|
/// <param name="skip">Datensätze auslassen</param>
|
|
/// <param name="take">Datensätze nehmen</param>
|
|
/// <returns>Liste gefudene Walks</returns>
|
|
public async Task<(int total, List<WalkWithNames> list)> GetNextWithNamesForWalkerAsync(string dogWalkerId, DateTimeOffset date, int skip, int take)
|
|
{
|
|
var total = 0;
|
|
var list = new List<WalkWithNames>();
|
|
|
|
//1. Aktuell laufende Walks
|
|
var baseQuery = _namesRepository.QueryStoredProcedure("SELECT * FROM tv_WalksWithNames()", c => c.DogWalkerId == dogWalkerId && c.Deleted == false && c.Status == WalkStatus.Started);
|
|
//baseQuery = baseQuery.Where(c => c.Start <= date && c.End >= date);
|
|
//Anpassung, Walks auch dann anzeigen, wenn gestartet aber das Startdatum noch nicht erreicht ist
|
|
baseQuery = baseQuery.Where(c => c.End >= date);
|
|
list.AddRange(await baseQuery.OrderBy(c => c.Start).ToListAsync().ConfigureAwait(false));
|
|
|
|
//2. Nicht gestartete Walks
|
|
baseQuery = _namesRepository.QueryStoredProcedure("SELECT * FROM tv_WalksWithNames()", c => c.DogWalkerId == dogWalkerId && c.Deleted == false && c.Status == WalkStatus.Accepted && c.PaymentStatus == PaymentStatus.Authorized);
|
|
baseQuery = baseQuery.Where(c => c.Start <= date && c.End >= date);
|
|
list.AddRange(await baseQuery.OrderBy(c => c.Start).ToListAsync().ConfigureAwait(false));
|
|
|
|
//3. Nicht abgeschlossene Walks
|
|
baseQuery = _namesRepository.QueryStoredProcedure("SELECT * FROM tv_WalksWithNames()", c => c.DogWalkerId == dogWalkerId && c.Deleted == false && (c.Status == WalkStatus.Accepted || c.Status == WalkStatus.Started) && c.PaymentStatus == PaymentStatus.Authorized);
|
|
baseQuery = baseQuery.Where(c => c.End <= date);
|
|
list.AddRange(await baseQuery.OrderBy(c => c.Start).ToListAsync().ConfigureAwait(false));
|
|
|
|
//5. Nächster anstehender Walk
|
|
baseQuery = _namesRepository.QueryStoredProcedure("SELECT * FROM tv_WalksWithNames()", c => c.DogWalkerId == dogWalkerId && c.Deleted == false && c.Status == WalkStatus.Accepted && c.PaymentStatus == PaymentStatus.Authorized);
|
|
baseQuery = baseQuery.Where(c => c.Start >= date).OrderBy(c => c.Start);
|
|
var nextWaks = (await baseQuery.ToListAsync().ConfigureAwait(false)).Skip(0).Take(3);
|
|
if (nextWaks.Any())
|
|
list.AddRange(nextWaks);
|
|
|
|
total = list.Count;
|
|
list = list.Skip(skip).Take(take).ToList();
|
|
|
|
return (total, list);
|
|
}
|
|
|
|
/// <summary>
|
|
/// Gibt einen Walk mit Namen aufgelöst zurück
|
|
/// </summary>
|
|
/// <param name="walkId">Id des Walks</param>
|
|
/// <returns>Walk oder null, wenn nicht gefunden</returns>
|
|
public async Task<WalkWithNames> GetWalkWithNamesAsync(string walkId)
|
|
{
|
|
var baseQuery = _namesRepository.QueryStoredProcedure("SELECT * FROM tv_WalksWithNames()", c => c.Deleted == false);
|
|
baseQuery = baseQuery.Where(c => c.Id == walkId && c.Deleted == false);
|
|
|
|
return await baseQuery.FirstOrDefaultAsync().ConfigureAwait(false);
|
|
}
|
|
|
|
/// <summary>
|
|
/// Zurückgeben einer Liste von Walks die einen bestimmten Status haben
|
|
/// </summary>
|
|
/// <param name="status">Gesuchter Status</param>
|
|
/// <returns>Liste von Walks</returns>
|
|
public async Task<List<Walk>> GetByStatusAsync(WalkStatus status)
|
|
{
|
|
var walks = await Repository.FindAsync(c => c.Status == status && c.Deleted == false).ConfigureAwait(false);
|
|
return walks.ToList();
|
|
}
|
|
|
|
/// <summary>
|
|
/// Gibt einen Walk zurück der mit einer öffentlichen Anfrage verknüpft 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 walk = await Repository.FirstOrDefaultAsync(c => c.PublicWalkRequestId == publicWalkRequestId && c.Deleted == false).ConfigureAwait(false);
|
|
return walk;
|
|
}
|
|
|
|
/// <summary>
|
|
/// Prüft ob ein Walk für einen Zeitraum gebucht werden kann.
|
|
/// Sittings werden dabei ignoriert!
|
|
/// </summary>
|
|
/// <param name="dogWalkerId">Id des dogwalkers</param>
|
|
/// <param name="start">Startdatum</param>
|
|
/// <param name="end">Enddatum</param>
|
|
/// <returns>true wenn verfügbar, false sonst</returns>
|
|
public async Task<bool> IsWalkPossibleAsync(string dogWalkerId, DateTimeOffset start, DateTimeOffset end)
|
|
{
|
|
var walkFound = await Repository.FirstOrDefaultAsync(c => c.DogWalkerId == dogWalkerId && c.ServiceType == WalkServiceType.Walking && start < c.End && end > c.Start && c.Deleted == false && (c.Status == WalkStatus.Accepted || c.Status == WalkStatus.Started)).ConfigureAwait(false);
|
|
return walkFound == null;
|
|
}
|
|
|
|
/// <summary>
|
|
/// Setzt Walks die im Status "Request" sind auf Cancel.
|
|
/// Wird verwendet wenn eine FIXE buchung gemacht wird und andere noch auf eine Antwort warten.
|
|
/// </summary>
|
|
/// <param name="dogWalkerId">Id des dogwalkers</param>
|
|
/// <param name="start">Startdatum</param>
|
|
/// <param name="end">Enddatum</param>
|
|
/// <returns>Anzahl betroffene Walks</returns>
|
|
public async Task<int> CancelWalkRequestsAsync(string dogWalkerId, DateTimeOffset start, DateTimeOffset end)
|
|
{
|
|
var walks = await Repository.FindAsync(c => c.DogWalkerId == dogWalkerId && c.ServiceType == WalkServiceType.Walking && start < c.End && end > c.Start && c.Deleted == false && c.Status == WalkStatus.Requested).ConfigureAwait(false);
|
|
foreach (var walk in walks)
|
|
{
|
|
walk.Status = WalkStatus.Cancelled;
|
|
walk.CancelledBy = CancellationSource.GehGassi;
|
|
walk.CancelledReason = string.Empty;
|
|
walk.UpdatedAt = DateTimeOffset.UtcNow;
|
|
}
|
|
|
|
return walks.Count();
|
|
}
|
|
|
|
/// <summary>
|
|
/// Walks stornieren welche im Status Request sind und das Startdatum erreicht wurde
|
|
/// </summary>
|
|
/// <param name="date">Datum für Prüfung</param>
|
|
/// <returns>Anzahl timed out</returns>
|
|
public async Task<int> CancelTimedOutAsync(DateTimeOffset date)
|
|
{
|
|
var walks = await Repository.FindAsync(c => c.Start < DateTimeOffset.UtcNow && c.Deleted == false && c.Status == WalkStatus.Requested).ConfigureAwait(false);
|
|
foreach (var walk in walks)
|
|
{
|
|
walk.Status = WalkStatus.Cancelled;
|
|
walk.CancelledBy = CancellationSource.GehGassi;
|
|
walk.CancelledReason = string.Empty;
|
|
walk.UpdatedAt = DateTimeOffset.UtcNow;
|
|
}
|
|
|
|
return walks.Count();
|
|
}
|
|
|
|
/// <summary>
|
|
/// Stornieren von Walks die im Zahlungsstatus Pending sind und länger als X Minuten alt sind
|
|
/// </summary>
|
|
/// <param name="date">Datum für Prüfung</param>
|
|
/// <param name="minutes">Ablaufzeit in Minuten</param>
|
|
/// <returns>Anzahl storniert</returns>
|
|
public async Task<int> CancelPendingAsync(DateTimeOffset date, int minutes)
|
|
{
|
|
var publicWalkRequestService = (IPublicWalkRequestService)_serviceProvider.GetService(typeof(IPublicWalkRequestService));
|
|
var publicWalkResponseService = (IPublicWalkResponseService)_serviceProvider.GetService(typeof(IPublicWalkResponseService));
|
|
var voucherCampaignService = (IVoucherCampaignService)_serviceProvider.GetService(typeof(IVoucherCampaignService));
|
|
var customerService = (ICustomerService)_serviceProvider.GetService(typeof(ICustomerService));
|
|
var mangoPayService = (IMangoPayService)_serviceProvider.GetService(typeof(IMangoPayService));
|
|
|
|
var compareDate = date.AddMinutes(-minutes);
|
|
|
|
var walks = await Repository.FindAsync(c => c.PaymentStatus == PaymentStatus.Pending && c.Deleted == false && c.Status == WalkStatus.Accepted && c.Created < compareDate).ConfigureAwait(false);
|
|
foreach (var walk in walks)
|
|
{
|
|
if (!string.IsNullOrWhiteSpace(walk.VoucherId) && walk.VoucherAmmount > 0)
|
|
{
|
|
var usage = await voucherCampaignService.GetUsageAsync(walk.VoucherId, walk.DogOwnerId, walk.Id);
|
|
if (usage != null)
|
|
{
|
|
var voucher = await voucherCampaignService.GetVoucherAsync(usage.VoucherId);
|
|
if (voucher != null && voucher.Id == usage.VoucherId)
|
|
{
|
|
var campaign = await voucherCampaignService.GetAsync(voucher.VoucherCampaignId);
|
|
if (campaign != null)
|
|
{
|
|
var customer = await customerService.GetAsync(campaign.CustomerId);
|
|
if (customer != null)
|
|
{
|
|
//Geld vom Transferkonto der Kamapgne auf das Guthabenkonto überweisen mit Verweis auf den Walk und Transaktion erfassen
|
|
var ammount = (int)(usage.VoucherAmmountUsed * 100);
|
|
var transferResult = await mangoPayService.TransferMoneyAsync(customer.MangopayPaymentId, campaign.WalletFeeId,
|
|
customer.MangopayPaymentId, campaign.WalletCreditId, walk.Id, ammount, 0, $"VoucherId_{voucher.Id}_WalkId_{walk.Id}", "", "");
|
|
|
|
if (transferResult.Success)
|
|
{
|
|
//Usage beim voucher zurücksetzen (UsedCount, IsValid wenn Einzelgutschein)
|
|
voucher.UsedCount -= 1;
|
|
if (voucher.UsedCount < 0)
|
|
voucher.UsedCount = 0;
|
|
voucher.IsValid = true;
|
|
|
|
//Usage in der Kampagne zurücksetzen (VouchersUsed, BudgetUsed)
|
|
campaign.VouchersUsed -= 1;
|
|
if (campaign.VouchersUsed < 0)
|
|
campaign.VouchersUsed = 0;
|
|
campaign.BudgetUsed -= usage.VoucherAmmountUsed;
|
|
if (campaign.BudgetUsed < 0)
|
|
campaign.BudgetUsed = 0;
|
|
|
|
walk.VoucherId = null;
|
|
walk.VoucherAmmount = 0;
|
|
|
|
//Reservieren durch die Anlage einer VoucherUsage
|
|
voucherCampaignService.RemoveUsage(usage);
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
walk.Status = WalkStatus.Cancelled;
|
|
walk.CancelledBy = CancellationSource.GehGassi;
|
|
walk.CancelledReason = string.Empty;
|
|
walk.UpdatedAt = DateTimeOffset.UtcNow;
|
|
|
|
if (walk.Type == WalkType.OpenRequest)
|
|
{
|
|
var resetSuccess = await publicWalkRequestService.ResetAsync(walk.PublicWalkRequestId);
|
|
if (resetSuccess)
|
|
{
|
|
var reopenedCount = await publicWalkResponseService.SetOpenForClosedOrAcceptedAsync(walk.PublicWalkRequestId);
|
|
}
|
|
walk.PublicWalkRequestId = string.Empty;
|
|
}
|
|
}
|
|
|
|
return walks.Count();
|
|
}
|
|
|
|
/// <summary>
|
|
/// Abschliessen eines Walks, falls das vergessen wurde
|
|
/// </summary>
|
|
/// <param name="date">Datum für Prüfung</param>
|
|
/// <param name="minutes">Ablaufzeit in Minuten</param>
|
|
/// <returns>Anzahl abgeschlossen</returns>
|
|
public async Task<int> CompleteAutoAsync(DateTimeOffset date, int minutes)
|
|
{
|
|
var compareDate = date.AddMinutes(-minutes);
|
|
|
|
var walks = await Repository.FindAsync(c => c.PaymentStatus == PaymentStatus.Authorized && c.Deleted == false && (c.Status == WalkStatus.Accepted || c.Status == WalkStatus.Started) && c.End < compareDate).ConfigureAwait(false);
|
|
foreach (var walk in walks)
|
|
{
|
|
walk.Status = WalkStatus.Completed;
|
|
walk.UpdatedAt = DateTimeOffset.UtcNow;
|
|
}
|
|
|
|
return walks.Count();
|
|
}
|
|
|
|
/// <summary>
|
|
/// Bestätigen von Walks die im Status Abgeschlossen sind und länger als X Minuten alt sind.
|
|
/// Löst die Überweisung von den Kosten für den Walk vom hundebesitzer an den Dogwalker aus.
|
|
/// </summary>
|
|
/// <param name="date">Datum für Prüfung</param>
|
|
/// <param name="minutes">Ablaufzeit in Minuten</param>
|
|
/// <returns>Anzahl bestätigt</returns>
|
|
public async Task<int> ConfirmCompletedAsync(DateTimeOffset date, int minutes)
|
|
{
|
|
var compareDate = date.AddMinutes(-minutes);
|
|
var mangoPayService = (IMangoPayService)_serviceProvider.GetService(typeof(IMangoPayService));
|
|
var gehGassiTransactionService = (ITransactionFeeService)_serviceProvider.GetService(typeof(ITransactionFeeService));
|
|
var walletService = (IWalletService)_serviceProvider.GetService(typeof(IWalletService));
|
|
var appUserService = (IAppUserService)_serviceProvider.GetService(typeof(IAppUserService));
|
|
var voucherCampaignService = (IVoucherCampaignService)_serviceProvider.GetService(typeof(IVoucherCampaignService));
|
|
var customerService = (ICustomerService)_serviceProvider.GetService(typeof(ICustomerService));
|
|
|
|
var walks = await Repository.FindAsync(c => c.Status == WalkStatus.Completed && c.Deleted == false && c.PaymentStatus == PaymentStatus.Authorized && c.Completed< compareDate).ConfigureAwait(false);
|
|
foreach (var walk in walks)
|
|
{
|
|
walk.Status = WalkStatus.Confirmed;
|
|
walk.Confirmed = DateTimeOffset.UtcNow;
|
|
walk.UpdatedAt = DateTimeOffset.UtcNow;
|
|
walk.PaymentStatus = PaymentStatus.Paid;
|
|
await CommitAsync("System");
|
|
|
|
if (walk.PaymentType == WalkPaymentType.MangoPay)
|
|
{
|
|
decimal feeDecimal = 0;
|
|
long feeFromUser = 0;
|
|
long feeFromVoucher = 0;
|
|
var gehGassiFee = await gehGassiTransactionService.GetMinGehGassiFeeAsync(walk.Price);
|
|
if (gehGassiFee != null)
|
|
{
|
|
if (gehGassiFee.Percent > 0)
|
|
{
|
|
var percent = walk.Price * gehGassiFee.Percent / 100;
|
|
feeDecimal = percent;
|
|
}
|
|
|
|
if (gehGassiFee.Fixed > 0)
|
|
{
|
|
feeDecimal += gehGassiFee.Fixed;
|
|
}
|
|
}
|
|
if (feeDecimal > 0)
|
|
{
|
|
feeFromUser = (long)(feeDecimal * 100);
|
|
}
|
|
|
|
|
|
//Wenn es einen gutschein gibt, dann Geld vom Transferkontos des Gutscheins auf das transferkonto des Hundebesitzers überweisen
|
|
if (!string.IsNullOrWhiteSpace(walk.VoucherId) && walk.VoucherAmmount > 0)
|
|
{
|
|
var voucherUsed = await voucherCampaignService.GetUsageAsync(walk.VoucherId, walk.DogOwnerId, walk.Id);
|
|
if (voucherUsed != null)
|
|
{
|
|
var ammountFromVoucher = (long)(voucherUsed.VoucherAmmountUsed * 100);
|
|
voucherUsed.UsageStatus = VoucherUsageStatus.Used;
|
|
await CommitAsync("System");
|
|
|
|
var voucher = await voucherCampaignService.GetVoucherAsync(voucherUsed.VoucherId);
|
|
if (voucher != null)
|
|
{
|
|
var campaign = await voucherCampaignService.GetAsync(voucher.VoucherCampaignId);
|
|
if (campaign != null)
|
|
{
|
|
var customer = await customerService.GetAsync(campaign.CustomerId);
|
|
if (customer != null)
|
|
{
|
|
var dogOwner = await appUserService.GetAsync(walk.DogOwnerId);
|
|
if (dogOwner != null)
|
|
{
|
|
var wallet = await walletService.GetAsync(walk.DogOwnerId, WalletType.Fees);
|
|
if (wallet != null)
|
|
{
|
|
var transferResult = await mangoPayService.TransferMoneyAsync(customer.MangopayPaymentId, campaign.WalletFeeId, dogOwner.PaymentId, wallet.Id, walk.Id, ammountFromVoucher, 0, $"VoucherId_{voucher.Id}_WalkId_{walk.Id}", targetAppUserId: dogOwner.Id);
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
var sourceWallet = await walletService.GetAsync(walk.DogOwnerId, WalletType.Fees);
|
|
var targetWallet = await walletService.GetAsync(walk.DogWalkerId, WalletType.Credits);
|
|
if (sourceWallet != null && targetWallet != null)
|
|
{
|
|
var sourceUser = await appUserService.GetAsync(walk.DogOwnerId);
|
|
var targetUser = await appUserService.GetAsync(walk.DogWalkerId);
|
|
|
|
if (sourceUser != null && targetUser != null)
|
|
{
|
|
var ammount = (long)(walk.Price * 100);
|
|
var transcationSuccess = await mangoPayService.TransferMoneyAsync(walk.DogOwnerId, walk.DogWalkerId, walk.Id, ammount, feeFromUser, $"WalkId_Payment_{walk.Id}");
|
|
|
|
//Wallets aktualisieren
|
|
await mangoPayService.GetWalletBalanceAsync(sourceUser.Id, WalletType.Credits);
|
|
await mangoPayService.GetWalletBalanceAsync(sourceUser.Id, WalletType.Fees);
|
|
|
|
await mangoPayService.GetWalletBalanceAsync(targetUser.Id, WalletType.Credits);
|
|
await mangoPayService.GetWalletBalanceAsync(targetUser.Id, WalletType.Fees);
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
return walks.Count();
|
|
}
|
|
|
|
/// <summary>
|
|
/// Bestätigen von Walks die im Status Abgeschlossen sind und länger als X Minuten alt sind.
|
|
/// Löst die Überweisung von den Kosten für den Walk vom hundebesitzer an den Dogwalker aus.
|
|
/// </summary>
|
|
/// <param name="date">Datum für Prüfung</param>
|
|
/// <param name="minutes">Ablaufzeit in Minuten</param>
|
|
/// <returns>Anzahl bestätigt</returns>
|
|
public async Task<int> ConfirmCompletedReminderAsync(DateTimeOffset date, int minutes)
|
|
{
|
|
var pushNotificationService = (IPushNotificationService)_serviceProvider.GetService(typeof(IPushNotificationService));
|
|
|
|
var compareDateLower = date.AddMinutes(-minutes - 1);
|
|
var compareDateUpper = date.AddMinutes(-minutes);
|
|
|
|
var walks = await Repository.FindAsync(c => c.Status == WalkStatus.Completed && c.Deleted == false && c.PaymentStatus == PaymentStatus.Authorized && c.Completed >= compareDateLower && c.Completed <= compareDateUpper).ConfigureAwait(false);
|
|
foreach (var walk in walks)
|
|
{
|
|
await pushNotificationService.SendWalkCompletedReminderAsync(walk.DogOwnerId, walk.Id);
|
|
}
|
|
|
|
return walks.Count();
|
|
}
|
|
|
|
/// <summary>
|
|
/// Storniert Liste von Walks zurück, welche für 2 App-User in Beziehung stehen wenn eine Blockierung stattgefunden hat.
|
|
/// Wird bidirektional gesucht, da nicht immer sichergestellt ist, dass einer Walker und einer Owner ist.
|
|
/// Es werden nur Walks im Status Requested oder Accepted berücksichtigt
|
|
/// </summary>
|
|
/// <param name="blockingAppUserId">Id des App-Users der blockiert hat</param>
|
|
/// <param name="blockedAppUserId">Id des App-Users der blockiert wurde</param>
|
|
/// <returns>Anzahl stornierte Walks</returns>
|
|
public async Task<int> CancelWalksForBlockAsync(string blockingAppUserId, string blockedAppUserId)
|
|
{
|
|
var mangoPayService = (IMangoPayService)_serviceProvider.GetService(typeof(IMangoPayService));
|
|
var systemMessageService = (ISystemMessageService)_serviceProvider.GetService(typeof(ISystemMessageService));
|
|
var pushNotificationService = (IPushNotificationService)_serviceProvider.GetService(typeof(IPushNotificationService));
|
|
|
|
var walks = await Repository.FindAsync(c => c.Status <= WalkStatus.Accepted && c.Deleted == false && ((c.DogOwnerId == blockingAppUserId && c.DogWalkerId == blockedAppUserId) || (c.DogOwnerId == blockedAppUserId && c.DogWalkerId == blockingAppUserId))).ConfigureAwait(false);
|
|
|
|
foreach (var walk in walks)
|
|
{
|
|
walk.Status = WalkStatus.Cancelled;
|
|
walk.UpdatedAt = DateTimeOffset.UtcNow;
|
|
walk.CancelledBy = CancellationSource.GehGassi;
|
|
walk.CancelledReason = "User blocked";
|
|
|
|
//Jetzt noch wegen Zahlungsstatus prüfen
|
|
if (walk.PaymentStatus == PaymentStatus.Paid || walk.PaymentStatus == PaymentStatus.Authorized)
|
|
{
|
|
//Zurücküberweisen der Summe vom Transaktionskonto auf das Guthabenkonto
|
|
if (walk.Price > 0)
|
|
{
|
|
var ammount = (long)(walk.Price * 100);
|
|
var tag = $"Walk_Cancel_{walk.Id}";
|
|
var refundResult = await mangoPayService.TransferMoneyFromFeeToCreditAccountAsync(walk.DogOwnerId, ammount, tag);
|
|
if (refundResult.Success)
|
|
walk.PaymentStatus = PaymentStatus.Refunded;
|
|
else
|
|
walk.PaymentStatus = PaymentStatus.Voided;
|
|
}
|
|
else
|
|
walk.PaymentStatus = PaymentStatus.Voided;
|
|
|
|
await CommitAsync("System");
|
|
|
|
//Wallets aktualisieren
|
|
await mangoPayService.GetWalletBalanceAsync(walk.DogOwnerId, WalletType.Credits);
|
|
await mangoPayService.GetWalletBalanceAsync(walk.DogOwnerId, WalletType.Fees);
|
|
|
|
systemMessageService.Add(walk.DogOwnerId, AppUserType.DogOwner, walk.Id, SystemMessageTables.Walk, SystemMessageType.WalkCancelled, DateTimeOffset.UtcNow.AddDays(14));
|
|
systemMessageService.Add(walk.DogWalkerId, AppUserType.DogWalker, walk.Id, SystemMessageTables.Walk, SystemMessageType.WalkCancelled, DateTimeOffset.UtcNow.AddDays(14));
|
|
await systemMessageService.CommitAsync("System");
|
|
|
|
await pushNotificationService.SendWalkCancelledAsync(walk.DogOwnerId, walk.Id, AppMode.DogOwner);
|
|
await pushNotificationService.SendWalkCancelledAsync(walk.DogWalkerId, walk.Id, AppMode.DogWalker);
|
|
}
|
|
}
|
|
|
|
return walks.Count();
|
|
}
|
|
|
|
/// <summary>
|
|
/// Stornieren aller Walks eines Benutzers der gesperrt wurde.
|
|
/// Wird bidirektional gesucht, da nicht immer sichergestellt ist, dass einer Walker und einer Owner ist.
|
|
/// Es werden nur Walks im Status Requested oder Accepted berücksichtigt
|
|
/// </summary>
|
|
/// <param name="appUserId">Id des App-Users</param>
|
|
/// <returns>Anzahl stornierte Walks</returns>
|
|
public async Task<int> CancelWalksForLockedAsync(string appUserId)
|
|
{
|
|
var mangoPayService = (IMangoPayService)_serviceProvider.GetService(typeof(IMangoPayService));
|
|
var systemMessageService = (ISystemMessageService)_serviceProvider.GetService(typeof(ISystemMessageService));
|
|
var pushNotificationService = (IPushNotificationService)_serviceProvider.GetService(typeof(IPushNotificationService));
|
|
|
|
var walks = await Repository.FindAsync(c => c.Status <= WalkStatus.Accepted && c.Deleted == false && (c.DogOwnerId == appUserId || c.DogWalkerId == appUserId)).ConfigureAwait(false);
|
|
|
|
foreach (var walk in walks)
|
|
{
|
|
walk.Status = WalkStatus.Cancelled;
|
|
walk.UpdatedAt = DateTimeOffset.UtcNow;
|
|
walk.CancelledBy = CancellationSource.GehGassi;
|
|
walk.CancelledReason = "User locked";
|
|
|
|
//Jetzt noch wegen Zahlungsstatus prüfen
|
|
if (walk.PaymentStatus == PaymentStatus.Paid || walk.PaymentStatus == PaymentStatus.Authorized)
|
|
{
|
|
//Zurücküberweisen der Summe vom Transaktionskonto auf das Guthabenkonto
|
|
if (walk.Price > 0)
|
|
{
|
|
var ammount = (long)(walk.Price * 100);
|
|
var tag = $"Walk_Cancel_{walk.Id}";
|
|
var refundResult = await mangoPayService.TransferMoneyFromFeeToCreditAccountAsync(walk.DogOwnerId, ammount, tag);
|
|
if (refundResult.Success)
|
|
walk.PaymentStatus = PaymentStatus.Refunded;
|
|
else
|
|
walk.PaymentStatus = PaymentStatus.Voided;
|
|
}
|
|
else
|
|
walk.PaymentStatus = PaymentStatus.Voided;
|
|
|
|
await CommitAsync("System");
|
|
|
|
//Wallets aktualisieren
|
|
await mangoPayService.GetWalletBalanceAsync(walk.DogOwnerId, WalletType.Credits);
|
|
await mangoPayService.GetWalletBalanceAsync(walk.DogOwnerId, WalletType.Fees);
|
|
|
|
//Es werden nur Nachrichten an den nicht gesperrten Benutzer gesendet
|
|
if(walk.DogOwnerId != appUserId)
|
|
systemMessageService.Add(walk.DogOwnerId, AppUserType.DogOwner, walk.Id, SystemMessageTables.Walk, SystemMessageType.WalkCancelled, DateTimeOffset.UtcNow.AddDays(14));
|
|
else
|
|
systemMessageService.Add(walk.DogWalkerId, AppUserType.DogWalker, walk.Id, SystemMessageTables.Walk, SystemMessageType.WalkCancelled, DateTimeOffset.UtcNow.AddDays(14));
|
|
await systemMessageService.CommitAsync("System");
|
|
|
|
if (walk.DogOwnerId != appUserId)
|
|
await pushNotificationService.SendWalkCancelledAsync(walk.DogOwnerId, walk.Id, AppMode.DogOwner);
|
|
else
|
|
await pushNotificationService.SendWalkCancelledAsync(walk.DogWalkerId, walk.Id, AppMode.DogWalker);
|
|
}
|
|
}
|
|
|
|
return walks.Count();
|
|
}
|
|
|
|
/// <summary>
|
|
/// Fügt die Verwendung eines Gutscheins zu einem Walk hinzu
|
|
/// </summary>
|
|
/// <param name="walkId">Id des Walks</param>
|
|
/// <param name="voucherId">Id des Gutscheins</param>
|
|
/// <param name="ammount">Verwendeter Gutscheinwert</param>
|
|
/// <returns>true wenn erfolgreich, false sonst</returns>
|
|
public async Task<bool> AddVoucherToWalk(string walkId, string voucherId, decimal ammount)
|
|
{
|
|
var walk = await Repository.FirstOrDefaultAsync(c => c.Id == walkId && c.Deleted == false).ConfigureAwait(false);
|
|
if (walk != null)
|
|
{
|
|
walk.VoucherId = voucherId;
|
|
walk.VoucherAmmount = ammount;
|
|
return true;
|
|
}
|
|
|
|
return false;
|
|
}
|
|
|
|
/// <summary>
|
|
/// Entfernt die Verwendung eines Gutscheins zu einem Walk
|
|
/// </summary>
|
|
/// <param name="walkId">Id des Walks</param>
|
|
/// <param name="voucherId">Id des Gutscheins</param>
|
|
/// <returns>true wenn erfolgreich, false sonst</returns>
|
|
public async Task<bool> RemoveVoucherFromWalk(string walkId, string voucherId)
|
|
{
|
|
var walk = await Repository.FirstOrDefaultAsync(c => c.Id == walkId && c.Deleted == false).ConfigureAwait(false);
|
|
if (walk != null && walk.VoucherId == voucherId)
|
|
{
|
|
walk.VoucherId = null;
|
|
walk.VoucherAmmount = 0;
|
|
return true;
|
|
}
|
|
|
|
return false;
|
|
}
|
|
|
|
/// <summary>
|
|
/// Gibt die Anzahl von Walks für einen Dogwalker mit dem Status Bestätigt in einem bestimmten Zeitraum zurück
|
|
/// </summary>
|
|
/// <param name="dogWalkerId">Id des DogWalkers</param>
|
|
/// <param name="startDate">StartDatum</param>
|
|
/// <param name="endDate">Enddatum</param>
|
|
/// <returns>Anzahl Walks</returns>
|
|
public async Task<int> CountConfirmedByTimeRangeAsync(string dogWalkerId, DateTimeOffset startDate, DateTimeOffset endDate)
|
|
{
|
|
var count = await Repository.CountAsync(c => c.DogWalkerId == dogWalkerId && c.Confirmed >= startDate && c.Confirmed <= endDate && c.Status == WalkStatus.Confirmed && c.Deleted == false).ConfigureAwait(false);
|
|
return count;
|
|
}
|
|
}
|
|
}
|