using AutoMapper;
using gehGassi.Core.Interfaces;
using gehGassi.Web.Helper;
using Microsoft.AspNetCore.Authentication.JwtBearer;
using Microsoft.AspNetCore.Authorization;
using Microsoft.AspNetCore.Mvc;
using Microsoft.Extensions.Logging;
using Microsoft.Extensions.Options;
using System.Threading.Tasks;
using gehGassi.Domain.Common;
using gehGassi.Domain.Walks;
using gehGassi.Dto.Walks;
using gehGassi.Dto.Common;
using gehGassi.Dto;
using NetTopologySuite.Geometries;
using NetTopologySuite;
using System;
using gehGassi.Dto.Dogs;
using System.Collections.Generic;
using System.Linq;
using System.Text.Json;
using gehGassi.Domain.Dogs;
using gehGassi.Dto.Messages;
using PublicWalkRequest = gehGassi.Domain.Walks.PublicWalkRequest;
using gehGassi.Persistence.Migrations;
using gehGassi.Web.Hubs;
using gehGassi.External.Services;
using gehGassi.Web.Services;
using Microsoft.Extensions.Localization;
using LocalizationOptions = gehGassi.Web.Helper.LocalizationOptions;
using System.Collections;
using gehGassi.Web.Auth;
using Asp.Versioning;
using gehGassi.Core.Services;
using Humanizer;
using Microsoft.AspNetCore.Authentication.Cookies;
namespace gehGassi.Web.Controllers.Api
{
///
/// Controller für die Verwaltung von Walks
///
[Authorize(AuthenticationSchemes = JwtBearerDefaults.AuthenticationScheme)]
[ApiController]
[ApiVersion(1)]
[Route("api/walks")]
[Route("api/v{v:apiVersion}/walks")]
public class ApiWalksController : ApiBaseController
{
private readonly ILogger _logger;
private readonly IGeoLocationService _geoLocationService;
private readonly IPublicWalkRequestService _publicWalkRequestService;
private readonly IPublicWalkResponseService _publicWalkResponseService;
private readonly IWalkService _walkService;
private readonly IDogService _dogService;
private readonly IRatingService _ratingService;
private readonly ISystemMessageService _systemMessageService;
private readonly IAppHubSender _appHubSender;
private readonly IMangoPayService _mangoPayService;
private readonly ITransactionFeeService _transactionFeeService;
private readonly IWalletService _walletService;
private readonly IWalkComplaintService _walkComplaintService;
private readonly IEmailSender _emailSender;
private readonly IOptions _walkComplaintOptions;
private readonly IStringLocalizer _localizer;
private readonly IPushNotificationService _pushNotificationService;
private readonly ICoinsService _coinsService;
private readonly IOptions _coinsOptions;
private readonly IVoucherCampaignService _voucherCampaignService;
private readonly ICustomerService _customerService;
private readonly IAppUserReportService _appUserReportService;
private readonly IUserService _userService;
private readonly ITicketStore _ticketStore;
private readonly IRefreshTokenService _refreshTokenService;
///
/// Erstellt eine Instanz
///
/// Instanz eines IMapper
/// Instanz eines ILogger
/// Instanz von LocalizationOptions
/// Instanz eines IDogOwnerService
/// Instanz eines IGeoLocationService
/// Instanz eines IPublicWalkRequestService
/// Instanz eines IPublicWalkResponseService
/// Instanz eines IWalkService
/// Instanz eines IDogService
/// Instanz eines IRatingService
/// Instanz eines ISystemMessageService
/// Instanz eines IAppHubSender
/// Instanz eines IMangoPayService
/// Instanz eines ITransactionFeeService
/// Instanz eines IWalletService
/// Instanz eines IWalkComplaintService
/// Instanz eines IEmailSender
/// Einstellungen für Reklamationen
/// Instanz eines IStringLocalizer
/// Instanz eines IPushNotificationService
/// Instanz eines ICoinsService
/// Instanz von CoinsOptions
/// Instanz eines IVoucherCampaignService
/// Instanz eines ICustomerService
/// Instanz eines IAppUserReportService
/// Instanz eines IUserService
/// Instanz eines ITicketStore
/// Instanz eines IRefreshTokenService
public ApiWalksController(IMapper mapper, ILogger logger, IOptions localizationOptions, IAppUserService appUserService,
IGeoLocationService geoLocationService, IPublicWalkRequestService publicWalkRequestService, IPublicWalkResponseService publicWalkResponseService,
IWalkService walkService, IDogService dogService, IRatingService ratingService, ISystemMessageService systemMessageService, IAppHubSender appHubSender,
IMangoPayService mangoPayService, ITransactionFeeService transactionFeeService, IWalletService walletService, IWalkComplaintService walkComplaintService,
IEmailSender emailSender, IOptions walkComplaintOptions, IStringLocalizer localizer, IPushNotificationService pushNotificationService,
ICoinsService coinsService, IOptions coinsOptions, IVoucherCampaignService voucherCampaignService, ICustomerService customerService, IAppUserReportService appUserReportService,
IUserService userService, ITicketStore ticketStore, IRefreshTokenService refreshTokenService) : base(mapper, localizationOptions, appUserService)
{
_logger = logger;
_geoLocationService = geoLocationService;
_publicWalkRequestService = publicWalkRequestService;
_publicWalkResponseService = publicWalkResponseService;
_walkService = walkService;
_dogService = dogService;
_ratingService = ratingService;
_systemMessageService = systemMessageService;
_appHubSender = appHubSender;
_mangoPayService = mangoPayService;
_transactionFeeService = transactionFeeService;
_walletService = walletService;
_walkComplaintService = walkComplaintService;
_emailSender = emailSender;
_walkComplaintOptions = walkComplaintOptions;
_localizer = localizer;
_pushNotificationService = pushNotificationService;
_coinsService = coinsService;
_coinsOptions = coinsOptions;
_voucherCampaignService = voucherCampaignService;
_customerService = customerService;
_appUserReportService = appUserReportService;
_userService = userService;
_ticketStore = ticketStore;
_refreshTokenService = refreshTokenService;
}
///
/// Abfrage der öffentlichen Anfragen eines AppUsers
///
/// Id des AppUsers
/// Letztes Update oder null, wenn noch keines
/// Liste der Anfragen
[HttpGet]
[Route("GetPublicWalkRequestsForSync")]
public async Task GetPublicWalkRequestsForSync(string appUserId, DateTimeOffset? lastUpdate)
{
var clientOffset = GetClientDateOffset();
if (User?.Identity != null && User.Identity.IsAuthenticated)
{
var requests = await _publicWalkRequestService.GetForSyncAppAsync(appUserId, lastUpdate);
var dtoList = Mapper.Map>(requests);
return Ok(dtoList);
}
return NotFound(CommunicationErrors.Common_NotFound);
}
///
/// Abfrage der öffentlichen Anfragen eines AppUsers "Latest"
///
/// Id des AppUsers
/// Gewünschte Sprache
/// Anahl gewünschte Anfragen
/// Liste der Anfragen
[HttpGet]
[Route("GetPublicWalkRequestsLatest")]
public async Task GetPublicWalkRequestsLatest(string appUserId, string language, int take)
{
var clientOffset = GetClientDateOffset();
if (User?.Identity != null && User.Identity.IsAuthenticated)
{
var baseAddress = GetBaseAddress();
var requests = await _publicWalkRequestService.GetLatestAsync(appUserId, take);
foreach (var request in requests)
{
request.Dogs = new List();
if (!string.IsNullOrWhiteSpace(request.DogsJson))
{
var dogsList = JsonSerializer.Deserialize>(request.DogsJson, new JsonSerializerOptions(JsonSerializerDefaults.Web));
foreach (var dogItem in dogsList)
{
var dog = await _dogService.GetWithNamesAsync(dogItem.Id, language, LocalizationOptions.Value.DefaultCulture, true);
if (dog != null)
{
request.Dogs.Add(new DogMinInfo()
{
Id = dog.Id,
Index = dog.Index,
Version = dog.Version,
UpdatedAt = dog.UpdatedAt,
Deleted = dog.Deleted,
DogRaceId = dog.DogRaceId,
DogRaceName = dog.DogRaceName,
Name = dog.Name,
Photo = !string.IsNullOrWhiteSpace(dog.Photo) ? $"{baseAddress}/file/documents/thumbnails/{200}/{dog.Photo}" : string.Empty,
Sex = dog.Sex,
Size = dog.Size,
BirthDate = dog.BirthDate,
AverageRating = dog.RatingStatistics_AverageRating
});
}
}
}
}
var dtoList = Mapper.Map>(requests);
foreach (var dtoItem in dtoList)
{
if (!string.IsNullOrWhiteSpace(dtoItem.DogPhoto))
dtoItem.DogPhoto = $"{baseAddress}/file/documents/thumbnails/{200}/{dtoItem.DogPhoto}";
if (!string.IsNullOrWhiteSpace(dtoItem.DogOwnerPhoto))
dtoItem.DogOwnerPhoto = $"{baseAddress}/file/documents/thumbnails/{200}/{dtoItem.DogOwnerPhoto}";
if (!string.IsNullOrWhiteSpace(dtoItem.DogWalkerPhoto))
dtoItem.DogWalkerPhoto = $"{baseAddress}/file/documents/thumbnails/{200}/{dtoItem.DogWalkerPhoto}";
}
return Ok(dtoList);
}
return NotFound(CommunicationErrors.Common_NotFound);
}
///
/// Abfrage der öffentlichen Anfragen
///
/// Abfragemodel
/// Liste der Anfragen
[HttpPost]
[Route("GetPublicWalkRequests")]
public async Task GetPublicWalkRequests(PublicWalkRequestQueryDto model)
{
var clientOffset = GetClientDateOffset();
if (User?.Identity != null && User.Identity.IsAuthenticated)
{
var baseAddress = GetBaseAddress();
var response = new ListResponseDto();
//Geodaten holen.
//Entweder wurde lat und lng geliefert, oder wir müssen über den benutzer und den app-mode entscheiden
var (country, state) = await GetGeoDataAsync(model);
var sortList = Mapper.Map>(model.DynamicSortOrder);
var queryResult = await _publicWalkRequestService.GetAsync(model.IgnoreId, model.DogOwnerId, model.DogWalkerId, (PublicWalkRequestStatus?)model.Status, sortList, model.Location.Lat.Value, model.Location.Lng.Value, model.Skip, model.Take);
response.Total = queryResult.total;
foreach (var request in queryResult.list)
{
request.Dogs = new List();
if (!string.IsNullOrWhiteSpace(request.DogsJson))
{
var dogsList = JsonSerializer.Deserialize>(request.DogsJson, new JsonSerializerOptions(JsonSerializerDefaults.Web));
foreach (var dogItem in dogsList)
{
var dog = await _dogService.GetWithNamesAsync(dogItem.Id, model.Language, LocalizationOptions.Value.DefaultCulture, true);
if (dog != null)
{
request.Dogs.Add(new DogMinInfo()
{
Id = dog.Id,
Index = dog.Index,
Version = dog.Version,
UpdatedAt = dog.UpdatedAt,
Deleted = dog.Deleted,
DogRaceId = dog.DogRaceId,
DogRaceName = dog.DogRaceName,
Name = dog.Name,
Photo = !string.IsNullOrWhiteSpace(dog.Photo) ? $"{baseAddress}/file/documents/thumbnails/{200}/{dog.Photo}" : string.Empty,
Sex = dog.Sex,
Size = dog.Size,
BirthDate = dog.BirthDate,
AverageRating = dog.RatingStatistics_AverageRating
});
}
}
}
}
var dtoList = Mapper.Map>(queryResult.list);
foreach (var dtoItem in dtoList)
{
if (!string.IsNullOrWhiteSpace(dtoItem.DogPhoto))
dtoItem.DogPhoto = $"{baseAddress}/file/documents/thumbnails/{200}/{dtoItem.DogPhoto}";
if (!string.IsNullOrWhiteSpace(dtoItem.DogOwnerPhoto))
dtoItem.DogOwnerPhoto = $"{baseAddress}/file/documents/thumbnails/{200}/{dtoItem.DogOwnerPhoto}";
if (!string.IsNullOrWhiteSpace(dtoItem.DogWalkerPhoto))
dtoItem.DogWalkerPhoto = $"{baseAddress}/file/documents/thumbnails/{200}/{dtoItem.DogWalkerPhoto}";
}
response.List = dtoList;
response.Take = model.Take;
response.Skip = model.Skip;
return Ok(response);
}
return NotFound(CommunicationErrors.Common_NotFound);
}
///
/// Abfrage der öffentlichen Anfragen erweitert
///
/// Abfragemodel
/// Liste der Anfragen
[HttpPost]
[Route("GetPublicWalkRequestsEx")]
public async Task GetPublicWalkRequestsEx(PublicWalkRequestQueryExDto model)
{
var clientOffset = GetClientDateOffset();
if (User?.Identity != null && User.Identity.IsAuthenticated)
{
var baseAddress = GetBaseAddress();
var response = new ListResponseDto();
//Geodaten holen.
//Entweder wurde lat und lng geliefert, oder wir müssen über den benutzer und den app-mode entscheiden
var (country, state) = await GetGeoDataAsync(model);
var sortList = Mapper.Map>(model.DynamicSortOrder);
var queryResult = await _publicWalkRequestService.GetAsync(model.IgnoreId, model.DogOwnerId, model.DogWalkerId, (PublicWalkRequestStatus?)model.Status, model.MaxRadius, (PublicWalkRequestType?)model.Type, model.MinPrice, sortList, model.Location.Lat.Value, model.Location.Lng.Value, model.Skip, model.Take);
response.Total = queryResult.total;
foreach (var request in queryResult.list)
{
request.Dogs = new List();
if (!string.IsNullOrWhiteSpace(request.DogsJson))
{
var dogsList = JsonSerializer.Deserialize>(request.DogsJson, new JsonSerializerOptions(JsonSerializerDefaults.Web));
foreach (var dogItem in dogsList)
{
var dog = await _dogService.GetWithNamesAsync(dogItem.Id, model.Language, LocalizationOptions.Value.DefaultCulture, true);
if (dog != null)
{
request.Dogs.Add(new DogMinInfo()
{
Id = dog.Id,
Index = dog.Index,
Version = dog.Version,
UpdatedAt = dog.UpdatedAt,
Deleted = dog.Deleted,
DogRaceId = dog.DogRaceId,
DogRaceName = dog.DogRaceName,
Name = dog.Name,
Photo = !string.IsNullOrWhiteSpace(dog.Photo) ? $"{baseAddress}/file/documents/thumbnails/{200}/{dog.Photo}" : string.Empty,
Sex = dog.Sex,
Size = dog.Size,
BirthDate = dog.BirthDate,
AverageRating = dog.RatingStatistics_AverageRating
});
}
}
}
}
var dtoList = Mapper.Map>(queryResult.list);
foreach (var dtoItem in dtoList)
{
if (!string.IsNullOrWhiteSpace(dtoItem.DogPhoto))
dtoItem.DogPhoto = $"{baseAddress}/file/documents/thumbnails/{200}/{dtoItem.DogPhoto}";
if (!string.IsNullOrWhiteSpace(dtoItem.DogOwnerPhoto))
dtoItem.DogOwnerPhoto = $"{baseAddress}/file/documents/thumbnails/{200}/{dtoItem.DogOwnerPhoto}";
if (!string.IsNullOrWhiteSpace(dtoItem.DogWalkerPhoto))
dtoItem.DogWalkerPhoto = $"{baseAddress}/file/documents/thumbnails/{200}/{dtoItem.DogWalkerPhoto}";
}
response.List = dtoList;
response.Take = model.Take;
response.Skip = model.Skip;
return Ok(response);
}
return NotFound(CommunicationErrors.Common_NotFound);
}
///
/// Abfrage der öffentlichen Anfragen mit Antwort-Status für einen Dogwalker
///
/// Abfragemodel
/// Liste der Anfragen
[HttpPost]
[Route("GetPublicWalkRequestsAndResponseStatus")]
public async Task GetPublicWalkRequestsAndResponseStatus(PublicWalkRequestAndResponseStatusQueryDto model)
{
var clientOffset = GetClientDateOffset();
if (User?.Identity != null && User.Identity.IsAuthenticated)
{
var baseAddress = GetBaseAddress();
var response = new ListResponseDto();
//Geodaten holen.
//Entweder wurde lat und lng geliefert, oder wir müssen über den benutzer und den app-mode entscheiden
var (country, state) = await GetGeoDataAsync(model);
var sortList = Mapper.Map>(model.DynamicSortOrder);
var queryResult = await _publicWalkRequestService.GetWithResponseStatusAsync(model.IgnoreId, model.DogOwnerId, model.DogWalkerId, (PublicWalkRequestStatus?)model.Status, model.TargetDogWalkerId, (PublicWalkResponseStatus?)model.ResponseStatus, model.MustHaveResponse, sortList, model.Location.Lat.Value, model.Location.Lng.Value, model.IncludeBlockedAndLocked, model.Skip, model.Take);
response.Total = queryResult.total;
foreach (var request in queryResult.list)
{
request.Dogs = new List();
if (!string.IsNullOrWhiteSpace(request.DogsJson))
{
var dogsList = JsonSerializer.Deserialize>(request.DogsJson, new JsonSerializerOptions(JsonSerializerDefaults.Web));
foreach (var dogItem in dogsList)
{
var dog = await _dogService.GetWithNamesAsync(dogItem.Id, model.Language, LocalizationOptions.Value.DefaultCulture, true);
if (dog != null)
{
request.Dogs.Add(new DogMinInfo()
{
Id = dog.Id,
Index = dog.Index,
Version = dog.Version,
UpdatedAt = dog.UpdatedAt,
Deleted = dog.Deleted,
DogRaceId = dog.DogRaceId,
DogRaceName = dog.DogRaceName,
Name = dog.Name,
Photo = !string.IsNullOrWhiteSpace(dog.Photo) ? $"{baseAddress}/file/documents/thumbnails/{200}/{dog.Photo}" : string.Empty,
Sex = dog.Sex,
Size = dog.Size,
BirthDate = dog.BirthDate,
AverageRating = dog.RatingStatistics_AverageRating
});
}
else
{
request.Dogs.Add(new DogMinInfo()
{
Id = dogItem.Id,
Index = 0,
Version = null,
UpdatedAt = DateTimeOffset.UtcNow,
Deleted = false,
DogRaceId = string.Empty,
DogRaceName = string.Empty,
Name = dogItem.Name,
Photo = string.Empty,
AverageRating = 0,
Sex = DogSex.MaleDog,
Size = DogSize.Middle
});
}
}
}
}
var dtoList = Mapper.Map>(queryResult.list);
foreach (var dtoItem in dtoList)
{
if (string.IsNullOrWhiteSpace(dtoItem.DogPhoto))
dtoItem.DogPhoto = string.Empty;
if (string.IsNullOrWhiteSpace(dtoItem.DogOwnerPhoto))
dtoItem.DogOwnerPhoto = string.Empty;
if (string.IsNullOrWhiteSpace(dtoItem.DogWalkerPhoto))
dtoItem.DogWalkerPhoto = string.Empty;
if (!string.IsNullOrWhiteSpace(dtoItem.DogPhoto))
dtoItem.DogPhoto = $"{baseAddress}/file/documents/thumbnails/{200}/{dtoItem.DogPhoto}";
if (!string.IsNullOrWhiteSpace(dtoItem.DogOwnerPhoto))
dtoItem.DogOwnerPhoto = $"{baseAddress}/file/documents/thumbnails/{200}/{dtoItem.DogOwnerPhoto}";
if (!string.IsNullOrWhiteSpace(dtoItem.DogWalkerPhoto))
dtoItem.DogWalkerPhoto = $"{baseAddress}/file/documents/thumbnails/{200}/{dtoItem.DogWalkerPhoto}";
if (string.IsNullOrWhiteSpace(dtoItem.DogName) && dtoItem.Dogs.Count > 0)
{
dtoItem.DogName = dtoItem.Dogs[0].Name;
}
}
response.List = dtoList;
response.Take = model.Take;
response.Skip = model.Skip;
return Ok(response);
}
return NotFound(CommunicationErrors.Common_NotFound);
}
///
/// Abfrage der öffentlichen Anfragen mit Antwort-Status für einen Dogwalker - erweitert um suchparameter
///
/// Abfragemodel
/// Liste der Anfragen
[HttpPost]
[Route("GetPublicWalkRequestsAndResponseStatusEx")]
public async Task GetPublicWalkRequestsAndResponseStatusEx(PublicWalkRequestAndResponseStatusQueryExDto model)
{
var clientOffset = GetClientDateOffset();
if (User?.Identity != null && User.Identity.IsAuthenticated)
{
var baseAddress = GetBaseAddress();
var response = new ListResponseDto();
//Geodaten holen.
//Entweder wurde lat und lng geliefert, oder wir müssen über den benutzer und den app-mode entscheiden
var (country, state) = await GetGeoDataAsync(model);
var sortList = Mapper.Map>(model.DynamicSortOrder);
var queryResult = await _publicWalkRequestService.GetWithResponseStatusAsync(model.IgnoreId, model.DogOwnerId, model.DogWalkerId, (PublicWalkRequestStatus?)model.Status, model.TargetDogWalkerId, (PublicWalkResponseStatus?)model.ResponseStatus, model.MaxRadius, (PublicWalkRequestType?)model.Type, model.MinPrice, model.MustHaveResponse, model.SearchText, sortList, model.Location.Lat.Value, model.Location.Lng.Value, model.IncludeBlockedAndLocked, model.Skip, model.Take);
response.Total = queryResult.total;
foreach (var request in queryResult.list)
{
request.Dogs = new List();
if (!string.IsNullOrWhiteSpace(request.DogsJson))
{
var dogsList = JsonSerializer.Deserialize>(request.DogsJson, new JsonSerializerOptions(JsonSerializerDefaults.Web));
foreach (var dogItem in dogsList)
{
var dog = await _dogService.GetWithNamesAsync(dogItem.Id, model.Language, LocalizationOptions.Value.DefaultCulture, true);
if (dog != null)
{
request.Dogs.Add(new DogMinInfo()
{
Id = dog.Id,
Index = dog.Index,
Version = dog.Version,
UpdatedAt = dog.UpdatedAt,
Deleted = dog.Deleted,
DogRaceId = dog.DogRaceId,
DogRaceName = dog.DogRaceName,
Name = dog.Name,
Photo = !string.IsNullOrWhiteSpace(dog.Photo) ? $"{baseAddress}/file/documents/thumbnails/{200}/{dog.Photo}" : string.Empty,
Sex = dog.Sex,
Size = dog.Size,
BirthDate = dog.BirthDate,
AverageRating = dog.RatingStatistics_AverageRating
});
}
}
}
}
var dtoList = Mapper.Map>(queryResult.list);
foreach (var dtoItem in dtoList)
{
if (!string.IsNullOrWhiteSpace(dtoItem.DogPhoto))
dtoItem.DogPhoto = $"{baseAddress}/file/documents/thumbnails/{200}/{dtoItem.DogPhoto}";
if (!string.IsNullOrWhiteSpace(dtoItem.DogOwnerPhoto))
dtoItem.DogOwnerPhoto = $"{baseAddress}/file/documents/thumbnails/{200}/{dtoItem.DogOwnerPhoto}";
if (!string.IsNullOrWhiteSpace(dtoItem.DogWalkerPhoto))
dtoItem.DogWalkerPhoto = $"{baseAddress}/file/documents/thumbnails/{200}/{dtoItem.DogWalkerPhoto}";
}
response.List = dtoList;
response.Take = model.Take;
response.Skip = model.Skip;
return Ok(response);
}
return NotFound(CommunicationErrors.Common_NotFound);
}
///
/// Abfragen einer öffentlichen Anfrage
///
/// Id der Anfrage
/// Gewünschte Sprache
/// Anfrage
[HttpGet]
[Route("GetPublicWalkRequests")]
public async Task GetPublicWalkRequest(string id, string language)
{
var clientOffset = GetClientDateOffset();
if (User?.Identity != null && User.Identity.IsAuthenticated)
{
var request = await _publicWalkRequestService.GetWithNamesAsync(id);
if (request != null)
{
var appUserId = User.AppUserId();
var locked = await AppUserService.IsLockedAsync(request.DogOwnerId);
var blocked = await AppUserService.IsBlockedAsync(appUserId, request.DogOwnerId);
var baseAddress = GetBaseAddress();
request.Dogs = new List();
if (!string.IsNullOrWhiteSpace(request.DogsJson))
{
var dogsList = JsonSerializer.Deserialize>(request.DogsJson, new JsonSerializerOptions(JsonSerializerDefaults.Web));
foreach (var dogItem in dogsList)
{
var dog = await _dogService.GetWithNamesAsync(dogItem.Id, language, LocalizationOptions.Value.DefaultCulture, true);
if (dog != null)
{
request.Dogs.Add(new DogMinInfo()
{
Id = dog.Id,
Index = dog.Index,
Version = dog.Version,
UpdatedAt = dog.UpdatedAt,
Deleted = dog.Deleted,
DogRaceId = dog.DogRaceId,
DogRaceName = dog.DogRaceName,
Name = dog.Name,
Photo = !string.IsNullOrWhiteSpace(dog.Photo) ? $"{baseAddress}/file/documents/thumbnails/{200}/{dog.Photo}" : string.Empty,
Sex = dog.Sex,
Size = dog.Size,
BirthDate = dog.BirthDate,
AverageRating = dog.RatingStatistics_AverageRating,
});
}
}
}
var dto = Mapper.Map(request);
dto.Locked = locked;
dto.Blocked = blocked;
foreach (var dogMinInfoDto in dto.Dogs)
{
dogMinInfoDto.Locked = locked;
dogMinInfoDto.Blocked = blocked;
}
if (!string.IsNullOrWhiteSpace(dto.DogPhoto))
dto.DogPhoto = $"{baseAddress}/file/documents/thumbnails/{200}/{dto.DogPhoto}";
if (!string.IsNullOrWhiteSpace(dto.DogOwnerPhoto))
dto.DogOwnerPhoto = $"{baseAddress}/file/documents/thumbnails/{200}/{dto.DogOwnerPhoto}";
if (!string.IsNullOrWhiteSpace(dto.DogWalkerPhoto))
dto.DogWalkerPhoto = $"{baseAddress}/file/documents/thumbnails/{200}/{dto.DogWalkerPhoto}";
return Ok(dto);
}
}
return NotFound(CommunicationErrors.Common_NotFound);
}
///
/// Anlegen einer öffentlichen Anfrage
///
/// CreateConversationDto
/// HTTP 200 OK, Felher sonst
[HttpPost]
[Route("CreatePublicWalkRequest")]
public async Task CreatePublicWalkRequest(PublicWalkRequestCreateDto model)
{
var clientOffset = GetClientDateOffset();
var result = new CreateResponseDto
{
Status = CreateStatusDto.Error,
Value = null
};
if (User?.Identity != null && User.Identity.IsAuthenticated)
{
if (ModelState.IsValid)
{
var appUser = await AppUserService.GetAsync(model.DogOwnerId);
var existing = await _publicWalkRequestService.GetAsync(model.Id);
if (existing == null)
{
var publicWalkRequest = Mapper.Map(model);
var geometryFactory = NtsGeometryServices.Instance.CreateGeometryFactory(srid: 4326);
var geoLocation = geometryFactory.CreatePoint(new Coordinate(model.Lng, model.Lat));
publicWalkRequest.Location = geoLocation;
publicWalkRequest.DogWalkerId = string.Empty;
publicWalkRequest.PublicWalkResponseId = string.Empty;
publicWalkRequest.ResponseCount = 0;
publicWalkRequest.Status = PublicWalkRequestStatus.Open;
//Anzahl der Öffentlichen Anfragen prüfen die seit einer Stunde im Status Offen oder vergeben sind. Wenn es mehr als 4 sind, dann nicht anlegen und so tun als ob alles passt.
//TODO: Mindestminuten wieder entfernen wenn das mit dem Hacker vorbei ist.
var minMinutes = 30;
var minutes = (model.EndDate - model.StartDate).TotalMinutes;
var createdLastHour = await _publicWalkRequestService.CountByCreationDateAsync(model.Created.AddHours(-1), model.Created, model.DogOwnerId, PublicWalkRequestStatus.Placed);
if (createdLastHour >= 4 || (appUser != null && appUser.Locked) || minutes < minMinutes)
{
//Wenn innerhalb von 30 Minuten 4 öffnetliche Anfragen erstellt wurden, dann den User sperren
var createdLastTwentyMinutes = await _publicWalkRequestService.CountByCreationDateAsync(model.Created.AddMinutes(-30), model.Created, model.DogOwnerId, PublicWalkRequestStatus.Placed);
if (createdLastTwentyMinutes >= 4)
{
if (appUser != null)
{
appUser.Locked = true;
appUser.LockedReason = "Suspicious behavior - verächtiges Verhalten";
appUser.LockedUntil = DateTimeOffset.UtcNow.AddYears(5);
await AppUserService.CommitAsync("System");
//Echten Benutzer sperren
var user = await _userService.GetByAppUserAsync(appUser.Id);
if (user != null)
{
user.LockoutEnd = DateTimeOffset.UtcNow.AddYears(5);
await _userService.CommitAsync("System");
await _ticketStore.RemoveAsync(user.UserName);
await _refreshTokenService.RemoveAllAsync(user.Id, User.Identity.Name);
await _refreshTokenService.CommitAsync("System");
}
//Jetzt noch alle öffentlichen Anfragen des Users stornieren
var counter = 0;
var publicWalkRequestsOpen = await _publicWalkRequestService.GetByStatusAsync(appUser.Id, PublicWalkRequestStatus.Open);
foreach (var walkRequest in publicWalkRequestsOpen)
{
counter += 1;
walkRequest.Status = PublicWalkRequestStatus.Cancelled;
walkRequest.UpdatedAt = DateTimeOffset.UtcNow;
}
var publicWalkRequestsPlaced = await _publicWalkRequestService.GetByStatusAsync(appUser.Id, PublicWalkRequestStatus.Placed);
foreach (var walkRequest in publicWalkRequestsPlaced)
{
counter += 1;
walkRequest.Status = PublicWalkRequestStatus.Cancelled;
walkRequest.UpdatedAt = DateTimeOffset.UtcNow;
}
if (counter > 0)
await _publicWalkRequestService.CommitAsync("System");
}
}
result.Status = CreateStatusDto.Success;
result.Value = Mapper.Map(publicWalkRequest);
return Ok(result);
}
_publicWalkRequestService.Add(publicWalkRequest);
await _publicWalkRequestService.CommitAsync(User.Identity.Name);
var notification = _publicWalkRequestService.CreateNotification(publicWalkRequest.Id, publicWalkRequest.DogOwnerId, publicWalkRequest.PickupAddress, geoLocation);
_publicWalkRequestService.AddNotification(notification);
await _publicWalkRequestService.CommitAsync(User.Identity.Name);
result.Status = CreateStatusDto.Success;
result.Value = Mapper.Map(publicWalkRequest);
}
else
{
result.Status = CreateStatusDto.Exists;
}
return Ok(result);
}
}
return BadRequest(CommunicationErrors.Common_Model_Invalid);
}
///
/// Aktualisieren einer öffentlichen Anfrage
///
/// PublicWalkRequestDto
/// HTTP 200 OK, Felher sonst
[HttpPost]
[Route("UpdatePublicWalkRequest")]
public async Task UpdatePublicWalkRequest(PublicWalkRequestDto model)
{
var clientOffset = GetClientDateOffset();
if (User?.Identity != null && User.Identity.IsAuthenticated)
{
if (ModelState.IsValid)
{
var request = await _publicWalkRequestService.GetAsync(model.Id);
if (request != null)
{
if (model.UpdatedAt > request.UpdatedAt)
{
Mapper.Map(model, request);
await _publicWalkRequestService.CommitAsync(User.Identity.Name);
}
return Ok();
}
return NotFound(CommunicationErrors.Common_NotFound);
}
return BadRequest(CommunicationErrors.Common_Model_Invalid);
}
return NotFound(CommunicationErrors.Common_NotFound);
}
///
/// Löschen einer öffentlichen Anfrage
///
/// PublicWalkRequestDto
/// Id des App-Users
/// 200OK
[HttpPost]
[Route("DeletePublicWalkRequest")]
public async Task DeletePublicWalkRequest(PublicWalkRequestDto model, [FromQuery] string appUserId)
{
var clientOffset = GetClientDateOffset();
if (User?.Identity != null && User.Identity.IsAuthenticated)
{
if (ModelState.IsValid)
{
var request = await _publicWalkRequestService.GetAsync(model.Id);
if (request != null)
{
var appUser = await AppUserService.GetAsync(appUserId);
if (appUser != null)
{
if (request.DogWalkerId == appUser.Id)
{
//TODO: Löschen von verbundenen Daten!
_publicWalkRequestService.Remove(request);
await _publicWalkRequestService.CommitAsync(User.Identity.Name);
return Ok();
}
}
}
return NotFound(CommunicationErrors.Common_NotFound);
}
return BadRequest(CommunicationErrors.Common_Model_Invalid);
}
return NotFound(CommunicationErrors.Common_NotFound);
}
///
/// Akzeptieren einer Antwort zu einer öffentlichen Anfrage
///
/// PublicWalkRequestDto
/// HTTP 200 OK, Felher sonst
[HttpPost]
[Route("AcceptPublicWalkRequest")]
public async Task AcceptPublicWalkRequest(PublicWalkRequestAcceptDto model)
{
var clientOffset = GetClientDateOffset();
if (User?.Identity != null && User.Identity.IsAuthenticated)
{
if (ModelState.IsValid)
{
var request = await _publicWalkRequestService.GetAsync(model.PublicWalkRequestId);
if (request != null && request.DogOwnerId == model.DogOwnerId)
{
var response = await _publicWalkResponseService.GetAsync(model.PublicWalkResponseId);
if (response != null && response.PublicWalkRequestId == request.Id)
{
response.Status = PublicWalkResponseStatus.Accepted;
response.UpdatedAt = model.UpdatedAt;
await _publicWalkResponseService.CommitAsync(User.Identity.Name);
//Nun Completed setzen für alle anderen die Warten...
await _publicWalkResponseService.SetCompletedForWaitingAsync(request.Id);
await _publicWalkResponseService.CommitAsync(User.Identity.Name);
request.Status = PublicWalkRequestStatus.Placed;
request.PlacedDate = model.UpdatedAt;
request.PublicWalkResponseId = response.Id;
request.DogWalkerId = response.DogWalkerId;
request.UpdatedAt = model.UpdatedAt;
await _publicWalkResponseService.CommitAsync(User.Identity.Name);
//Nachricht an alle Angebote senden...
var responses = await _publicWalkResponseService.FindAsync(c => c.PublicWalkRequestId == request.Id);
foreach (var publicWalkResponse in responses.Where(c => c.DogWalkerId != request.DogWalkerId))
{
_systemMessageService.Add(publicWalkResponse.DogWalkerId, AppUserType.DogWalker, request.Id, SystemMessageTables.PublicWalkRequest, SystemMessageType.PublicWalkRequestChanged, DateTimeOffset.UtcNow.AddDays(14));
await _pushNotificationService.SendPublicWalkRequestChangedAsync(publicWalkResponse.DogWalkerId, request.Id);
}
await _systemMessageService.CommitAsync(User.Identity.Name);
foreach (var publicWalkResponse in responses.Where(c => c.DogWalkerId != request.DogWalkerId))
{
await _appHubSender.SystemMessageAddedAsync(publicWalkResponse.DogWalkerId);
}
//Nun einen Walk anlgegen!
var geometryFactory = NtsGeometryServices.Instance.CreateGeometryFactory(srid: 4326);
var geoLocation = geometryFactory.CreatePoint(new Coordinate(request.Location.X, request.Location.Y));
var walk = _walkService.Create();
walk.Type = WalkType.OpenRequest;
walk.ServiceType = request.RequestType == PublicWalkRequestType.Sitting ? WalkServiceType.Sitting : WalkServiceType.Walking;
walk.DogWalkerId = request.DogWalkerId;
walk.DogOwnerId = request.DogOwnerId;
walk.PublicWalkRequestId = request.Id;
walk.DogsJson = request.DogsJson;
walk.DogCount = request.DogCount;
walk.Start = request.StartDate;
walk.End = request.EndDate;
walk.PickupAddress = request.PickupAddress.Clone();
walk.PickupLocation = geoLocation;
walk.ReturnAddress = request.PickupAddress.Clone();
walk.ReturnLocation = geoLocation;
walk.Price = response.Price;
walk.Info = request.Info;
walk.Status = WalkStatus.Accepted;
walk.Started = null;
walk.Completed = null;
walk.Confirmed = null;
walk.Complained = null;
walk.ComplainReason = string.Empty;
walk.DeclinedReason = string.Empty;
walk.CancelledReason = string.Empty;
walk.CancelledBy = CancellationSource.None;
walk.CompletedInfo = string.Empty;
walk.Defactation = false;
walk.PaymentStatus = PaymentStatus.Pending;
walk.UpdatedAt = DateTimeOffset.UtcNow;
walk.Created = DateTimeOffset.UtcNow;
if (walk.Price == 0)
walk.PaymentStatus = PaymentStatus.Authorized;
_walkService.Add(walk);
await _walkService.CommitAsync(User.Identity.Name);
if (walk.PaymentStatus is PaymentStatus.Authorized or PaymentStatus.Paid)
{
//Nachricht an den dogWalker senden
_systemMessageService.Add(walk.DogWalkerId, AppUserType.DogWalker, walk.Id, SystemMessageTables.Walk, SystemMessageType.WalkAdded, DateTimeOffset.UtcNow.AddDays(14));
await _systemMessageService.CommitAsync(User.Identity.Name);
await _appHubSender.SystemMessageAddedAsync(walk.DogWalkerId);
await _pushNotificationService.SendNewWalkAsync(walk.DogWalkerId, walk.Id);
}
var walkDto = Mapper.Map(walk);
return Ok(walkDto);
}
}
return NotFound(CommunicationErrors.Common_NotFound);
}
return BadRequest(CommunicationErrors.Common_Model_Invalid);
}
return NotFound(CommunicationErrors.Common_NotFound);
}
///
/// Stornieren einer öffentlichen Anfrage
///
/// PublicWalkRequestCancelDto
/// HTTP 200 OK, Felher sonst
[HttpPost]
[Route("CancelPublicWalkRequest")]
public async Task CancelPublicWalkRequest(PublicWalkRequestCancelDto model)
{
var clientOffset = GetClientDateOffset();
if (User?.Identity != null && User.Identity.IsAuthenticated)
{
if (ModelState.IsValid)
{
var request = await _publicWalkRequestService.GetAsync(model.PublicWalkRequestId);
if (request != null)
{
request.Status = PublicWalkRequestStatus.Cancelled;
request.UpdatedAt = model.UpdatedAt;
await _publicWalkRequestService.CommitAsync(User.Identity.Name);
//Nachricht an alle Angebote senden...
var responses = await _publicWalkResponseService.FindAsync(c => c.PublicWalkRequestId == request.Id);
foreach (var publicWalkResponse in responses)
{
_systemMessageService.Add(publicWalkResponse.DogWalkerId, AppUserType.DogWalker, request.Id, SystemMessageTables.PublicWalkRequest, SystemMessageType.PublicWalkRequestCancelled, DateTimeOffset.UtcNow.AddDays(14));
await _pushNotificationService.SendPublicWalkRequestCancelledAsync(publicWalkResponse.DogWalkerId, request.Id);
}
await _systemMessageService.CommitAsync(User.Identity.Name);
foreach (var publicWalkResponse in responses)
{
await _appHubSender.SystemMessageAddedAsync(publicWalkResponse.DogWalkerId);
}
return Ok();
}
return NotFound(CommunicationErrors.Common_NotFound);
}
return BadRequest(CommunicationErrors.Common_Model_Invalid);
}
return NotFound(CommunicationErrors.Common_NotFound);
}
///
/// Anzahl der öffentlichen Anfragen eines AppUsers
///
/// Anzahl öffentliche Anfragen
[HttpGet]
[Route("CountPublicWalkRequests")]
public async Task CountPublicWalkRequests()
{
var clientOffset = GetClientDateOffset();
if (User?.Identity != null && User.Identity.IsAuthenticated)
{
var appUserId = User.AppUserId();
var requests = await _publicWalkRequestService.CountAsync(appUserId);
return Ok(requests);
}
return NotFound(CommunicationErrors.Common_NotFound);
}
///
/// Abfrage der Antworten auf öffentlichen Anfragen eines AppUsers
///
/// Id des AppUsers
/// Letztes Update oder null, wenn noch keines
/// Liste der Anfragen
[HttpGet]
[Route("GetPublicWalkResponsesForSync")]
public async Task GetPublicWalkResponsesForSync(string appUserId, DateTimeOffset? lastUpdate)
{
var clientOffset = GetClientDateOffset();
if (User?.Identity != null && User.Identity.IsAuthenticated)
{
var requests = await _publicWalkResponseService.GetForSyncAppAsync(appUserId, lastUpdate);
var dtoList = Mapper.Map>(requests);
return Ok(dtoList);
}
return NotFound(CommunicationErrors.Common_NotFound);
}
///
/// Abfrage einer Antwort auf öffentlichen Anfragen
///
/// Id der Antwort zur öffentlichen Anfrage
/// Liste der Anfragen
[HttpGet]
[Route("GetPublicWalkResponse")]
public async Task GetPublicWalkResponse(string publicWalkResponseId)
{
var clientOffset = GetClientDateOffset();
if (User?.Identity != null && User.Identity.IsAuthenticated)
{
var response = await _publicWalkResponseService.GetAsync(publicWalkResponseId);
if (response != null)
{
var dto = Mapper.Map(response);
return Ok(dto);
}
}
return NotFound(CommunicationErrors.Common_NotFound);
}
///
/// Abfrage einer Antwort auf öffentlichen Anfragen mit Namen aufgelöst
///
/// Id der Antwort zur öffentlichen Anfrage
/// Liste der Anfragen
[HttpGet]
[Route("GetPublicWalkResponseWithNames")]
public async Task GetPublicWalkResponseWithNames(string publicWalkResponseId)
{
var clientOffset = GetClientDateOffset();
if (User?.Identity != null && User.Identity.IsAuthenticated)
{
var appUserId = User.AppUserId();
var response = await _publicWalkResponseService.GetWithNamesAsync(appUserId, publicWalkResponseId);
if (response != null)
{
var dto = Mapper.Map(response);
var baseAddress = GetBaseAddress();
dto.DogWalkerPhoto = $"{baseAddress}/file/documents/thumbnails/{400}/{dto.DogWalkerPhoto}";
return Ok(dto);
}
}
return NotFound(CommunicationErrors.Common_NotFound);
}
///
/// Abfrage einer Antwort auf öffentlichen Anfragen eines Walkers
///
/// Id der öffentlichen Anfrage
/// Id des AppUsers
/// Liste der Anfragen
[HttpGet]
[Route("GetPublicWalkResponseForWalker")]
public async Task GetPublicWalkResponseForWalker(string publicWalkRequestId, string appUserId)
{
var clientOffset = GetClientDateOffset();
if (User?.Identity != null && User.Identity.IsAuthenticated)
{
var response = await _publicWalkResponseService.GetForWalkerAsync(appUserId, publicWalkRequestId);
if (response != null)
{
var dto = Mapper.Map(response);
return Ok(dto);
}
}
return NotFound(CommunicationErrors.Common_NotFound);
}
///
/// Anlegen einer Antwort zu einer öffentlichen Anfrage
///
/// PublicWalkResponseDto
/// HTTP 200 OK, Felher sonst
[HttpPost]
[Route("CreatePublicWalkResponse")]
public async Task CreatePublicWalkResponse(PublicWalkResponseDto model)
{
var clientOffset = GetClientDateOffset();
var result = new CreateResponseDto
{
Status = CreateStatusDto.Error,
Value = null
};
if (User?.Identity != null && User.Identity.IsAuthenticated)
{
if (ModelState.IsValid)
{
//Prüfen ob die Öffentliche Anfrage noch offen ist...
var publicWalkRequest = await _publicWalkRequestService.GetAsync(model.PublicWalkRequestId);
if (publicWalkRequest != null && !publicWalkRequest.Deleted && publicWalkRequest.Status == PublicWalkRequestStatus.Open)
{
var existing = await _publicWalkResponseService.GetAsync(model.Id);
if (existing == null)
{
var appUser = await AppUserService.GetAsync(model.DogWalkerId);
//TODO: Wenn der DogWalker gesperrt ist, kein Angebot zulassen
if (appUser is { Locked: true })
{
result.Status = CreateStatusDto.Error;
result.Value = null;
return Ok(result);
}
var appUserId = User.AppUserId();
var isBlocked = await AppUserService.IsBlockedAsync(publicWalkRequest.DogOwnerId, appUserId);
var publicWalkResponse = Mapper.Map(model);
publicWalkResponse.UpdatedAt = DateTimeOffset.UtcNow;
publicWalkResponse.Created = DateTimeOffset.UtcNow;
publicWalkResponse.Deleted = isBlocked;
_publicWalkResponseService.Add(publicWalkResponse);
await _publicWalkRequestService.CommitAsync(User.Identity.Name);
//Request aktualisieren....
if (publicWalkRequest != null && !isBlocked)
{
publicWalkRequest.ResponseCount = await _publicWalkResponseService.CountForPublicWalkRequestAsync(model.PublicWalkRequestId);
publicWalkRequest.UpdatedAt = DateTimeOffset.UtcNow;
await _publicWalkRequestService.CommitAsync(User.Identity.Name);
}
if (!isBlocked)
{
_systemMessageService.Add(publicWalkRequest.DogOwnerId, AppUserType.DogOwner, publicWalkRequest.Id, SystemMessageTables.PublicWalkRequest, SystemMessageType.PublicWalkResponseAdded, DateTimeOffset.UtcNow.AddDays(14));
await _systemMessageService.CommitAsync(User.Identity.Name);
await _appHubSender.SystemMessageAddedAsync(publicWalkRequest.DogOwnerId);
await _pushNotificationService.SendPublicWalkResponseAddedAsync(publicWalkRequest.DogOwnerId, publicWalkRequest.Id);
}
result.Status = CreateStatusDto.Success;
result.Value = Mapper.Map(publicWalkResponse);
}
else
{
result.Status = CreateStatusDto.Exists;
}
return Ok(result);
}
else
{
result.Status = CreateStatusDto.Error;
result.Value = null;
return Ok(result);
}
}
}
return BadRequest(CommunicationErrors.Common_Model_Invalid);
}
///
/// Aktualisieren einer Antwort zu einer öffentlichen Anfrage
///
/// PublicWalkRequestDto
/// HTTP 200 OK, Felher sonst
[HttpPost]
[Route("UpdatePublicWalkResponse")]
public async Task UpdatePublicWalkResponse(PublicWalkResponseDto model)
{
var clientOffset = GetClientDateOffset();
if (User?.Identity != null && User.Identity.IsAuthenticated)
{
if (ModelState.IsValid)
{
var response = await _publicWalkResponseService.GetAsync(model.Id);
if (response != null)
{
if (model.UpdatedAt > response.UpdatedAt && response.Status == PublicWalkResponseStatus.Awaiting)
{
Mapper.Map(model, response);
await _publicWalkResponseService.CommitAsync(User.Identity.Name);
//Request aktualisieren....
var publicWalkRequest = await _publicWalkRequestService.GetAsync(model.PublicWalkRequestId);
var appUser = User.AppUserId();
var isBlocked = await AppUserService.IsBlockedAsync(publicWalkRequest.DogOwnerId, appUser);
if (publicWalkRequest != null && !isBlocked)
{
publicWalkRequest.ResponseCount = await _publicWalkResponseService.CountForPublicWalkRequestAsync(model.PublicWalkRequestId);
publicWalkRequest.UpdatedAt = DateTimeOffset.UtcNow;
await _publicWalkRequestService.CommitAsync(User.Identity.Name);
}
}
return Ok();
}
return NotFound(CommunicationErrors.Common_NotFound);
}
return BadRequest(CommunicationErrors.Common_Model_Invalid);
}
return NotFound(CommunicationErrors.Common_NotFound);
}
///
/// Löschen einer Antwort zu einer öffentlichen Anfrage
///
/// PublicWalkRequestDto
/// Id des App-Users
/// 200OK
[HttpPost]
[Route("DeletePublicWalkResponse")]
public async Task DeletePublicWalkResponse(PublicWalkResponseDto model, [FromQuery] string appUserId)
{
var clientOffset = GetClientDateOffset();
if (User?.Identity != null && User.Identity.IsAuthenticated)
{
if (ModelState.IsValid)
{
var response = await _publicWalkResponseService.GetAsync(model.Id);
if (response != null)
{
var appUser = await AppUserService.GetAsync(appUserId);
if (appUser != null)
{
if (response.DogWalkerId == appUser.Id)
{
_publicWalkResponseService.Remove(response);
await _publicWalkResponseService.CommitAsync(User.Identity.Name);
//Request aktualisieren....
var publicWalkRequest = await _publicWalkRequestService.GetAsync(model.PublicWalkRequestId);
if (publicWalkRequest != null)
{
publicWalkRequest.ResponseCount = await _publicWalkResponseService.CountForPublicWalkRequestAsync(model.PublicWalkRequestId);
publicWalkRequest.UpdatedAt = DateTimeOffset.UtcNow;
await _publicWalkRequestService.CommitAsync(User.Identity.Name);
}
return Ok();
}
}
}
return NotFound(CommunicationErrors.Common_NotFound);
}
return BadRequest(CommunicationErrors.Common_Model_Invalid);
}
return NotFound(CommunicationErrors.Common_NotFound);
}
///
/// Abfrage der Antworten zu einer öffentlichen Anfragen
///
/// Abfragemodel
/// Liste der Anfragen
[HttpPost]
[Route("GetPublicWalkResponses")]
public async Task GetPublicWalkResponses(PublicWalkResponseQueryDto model)
{
var clientOffset = GetClientDateOffset();
if (User?.Identity != null && User.Identity.IsAuthenticated)
{
var response = new ListResponseDto();
//Geodaten holen.
//Entweder wurde lat und lng geliefert, oder wir müssen über den benutzer und den app-mode entscheiden
//var (country, state) = await GetGeoDataAsync(model);
var appUserId = User.AppUserId();
var queryResult = await _publicWalkResponseService.GetResponsesAsync(appUserId, model.PublicWalkRequestId, model.Skip, model.Take);
response.Total = queryResult.total;
var dtoList = Mapper.Map>(queryResult.list);
var baseAddress = GetBaseAddress();
foreach (var dtoItem in dtoList)
{
dtoItem.DogWalkerPhoto = !string.IsNullOrWhiteSpace(dtoItem.DogWalkerPhoto) ? $"{baseAddress}/file/documents/thumbnails/{200}/{dtoItem.DogWalkerPhoto}" : string.Empty;
}
response.List = dtoList;
response.Take = model.Take;
response.Skip = model.Skip;
return Ok(response);
}
return NotFound(CommunicationErrors.Common_NotFound);
}
///
/// Ablehenen eines Angebotes für eine öffentliche Anfrage
///
///
///
[HttpPost]
[Route("DeclinePublicWalkResponse")]
public async Task DeclinePublicWalkResponse(PublicWalkResponseDeclineDto model)
{
var clientOffset = GetClientDateOffset();
if (User?.Identity != null && User.Identity.IsAuthenticated)
{
if (ModelState.IsValid)
{
var response = await _publicWalkResponseService.GetAsync(model.PublicWalkResponseId);
if (response != null)
{
if (model.UpdatedAt > response.UpdatedAt && response.PublicWalkRequestId == model.PublicWalkRequestId && response.Status == PublicWalkResponseStatus.Awaiting)
{
response.Status = PublicWalkResponseStatus.Declined;
response.UpdatedAt = model.UpdatedAt;
await _publicWalkResponseService.CommitAsync(User.Identity.Name);
//Request aktualisieren....
var publicWalkRequest = await _publicWalkRequestService.GetAsync(model.PublicWalkRequestId);
if (publicWalkRequest != null)
{
publicWalkRequest.ResponseCount = await _publicWalkResponseService.CountForPublicWalkRequestAsync(model.PublicWalkRequestId);
publicWalkRequest.UpdatedAt = DateTimeOffset.UtcNow;
await _publicWalkRequestService.CommitAsync(User.Identity.Name);
}
_systemMessageService.Add(response.DogWalkerId, AppUserType.DogWalker, publicWalkRequest.Id, SystemMessageTables.PublicWalkRequest, SystemMessageType.PublicWalkResponseDeclined, DateTimeOffset.UtcNow.AddDays(14));
await _systemMessageService.CommitAsync(User.Identity.Name);
await _appHubSender.SystemMessageAddedAsync(response.DogWalkerId);
await _pushNotificationService.SendPublicWalkResponseDeclinedAsync(response.DogWalkerId, publicWalkRequest.Id);
}
return Ok();
}
return NotFound(CommunicationErrors.Common_NotFound);
}
return BadRequest(CommunicationErrors.Common_Model_Invalid);
}
return NotFound(CommunicationErrors.Common_NotFound);
}
///
/// Bearbeiten eines Bereits gestellten Angebotes für eine öffentliche Anfrage
///
/// PublicWalkResponseEditDto
/// 200OK
[HttpPost]
[Route("EditPublicWalkResponse")]
public async Task EditPublicWalkResponse(PublicWalkResponseEditDto model)
{
var clientOffset = GetClientDateOffset();
if (User?.Identity != null && User.Identity.IsAuthenticated)
{
if (ModelState.IsValid)
{
var response = await _publicWalkResponseService.GetAsync(model.PublicWalkResponseId);
if (response != null)
{
var publicWalkRequest = await _publicWalkRequestService.GetAsync(model.PublicWalkRequestId);
if (publicWalkRequest != null && !publicWalkRequest.Deleted && publicWalkRequest.Status == PublicWalkRequestStatus.Open)
{
if (model.UpdatedAt > response.UpdatedAt && response.Status == PublicWalkResponseStatus.Awaiting)
{
response.Price = model.Price;
response.Info = model.Info;
response.UpdatedAt = model.UpdatedAt;
await _publicWalkResponseService.CommitAsync(User.Identity.Name);
//Request aktualisieren....
if (publicWalkRequest != null)
{
publicWalkRequest.ResponseCount = await _publicWalkResponseService.CountForPublicWalkRequestAsync(model.PublicWalkRequestId);
publicWalkRequest.UpdatedAt = DateTimeOffset.UtcNow;
await _publicWalkRequestService.CommitAsync(User.Identity.Name);
}
_systemMessageService.Add(publicWalkRequest.DogOwnerId, AppUserType.DogOwner, publicWalkRequest.Id, SystemMessageTables.PublicWalkRequest, SystemMessageType.PublicWakResponseChanged, DateTimeOffset.UtcNow.AddDays(14));
await _systemMessageService.CommitAsync(User.Identity.Name);
await _appHubSender.SystemMessageAddedAsync(publicWalkRequest.DogOwnerId);
await _pushNotificationService.SendPublicWalkResponseChangedAsync(publicWalkRequest.DogOwnerId, publicWalkRequest.Id);
return Ok();
}
else
{
return Conflict(CommunicationErrors.Common_Entity_Changed);
}
}
else
{
return Conflict(CommunicationErrors.Common_Relation_Changed);
}
}
return NotFound(CommunicationErrors.Common_NotFound);
}
return BadRequest(CommunicationErrors.Common_Model_Invalid);
}
return NotFound(CommunicationErrors.Common_NotFound);
}
///
/// Stornieren eines bereits gestellten Angebotes für eine öffentliche Anfrage
///
/// PublicWalkResponseEditDto
/// 200OK
[HttpPost]
[Route("CancelPublicWalkResponse")]
public async Task CancelPublicWalkResponse(PublicWalkResponseCancelDto model)
{
var clientOffset = GetClientDateOffset();
if (User?.Identity != null && User.Identity.IsAuthenticated)
{
if (ModelState.IsValid)
{
var response = await _publicWalkResponseService.GetAsync(model.PublicWalkResponseId);
if (response != null)
{
var publicWalkRequest = await _publicWalkRequestService.GetAsync(model.PublicWalkRequestId);
if (publicWalkRequest != null && !publicWalkRequest.Deleted && publicWalkRequest.Status == PublicWalkRequestStatus.Open)
{
if (model.UpdatedAt > response.UpdatedAt && response.Status == PublicWalkResponseStatus.Awaiting)
{
response.Status = PublicWalkResponseStatus.Cancelled;
response.CancellationReason = model.CancellationReason;
response.UpdatedAt = model.UpdatedAt;
await _publicWalkResponseService.CommitAsync(User.Identity.Name);
//Request aktualisieren....
var appUser = User.AppUserId();
var isBlocked = await AppUserService.IsBlockedAsync(publicWalkRequest.DogOwnerId, appUser);
if (publicWalkRequest != null && !isBlocked)
{
publicWalkRequest.ResponseCount = await _publicWalkResponseService.CountForPublicWalkRequestAsync(model.PublicWalkRequestId);
publicWalkRequest.UpdatedAt = DateTimeOffset.UtcNow;
await _publicWalkRequestService.CommitAsync(User.Identity.Name);
}
if (!isBlocked)
{
_systemMessageService.Add(publicWalkRequest.DogOwnerId, AppUserType.DogOwner, publicWalkRequest.Id, SystemMessageTables.PublicWalkRequest, SystemMessageType.PublicWalkResponseCancelled, DateTimeOffset.UtcNow.AddDays(14));
await _systemMessageService.CommitAsync(User.Identity.Name);
await _appHubSender.SystemMessageAddedAsync(publicWalkRequest.DogOwnerId);
await _pushNotificationService.SendPublicWalkResponseCancelledAsync(publicWalkRequest.DogOwnerId, publicWalkRequest.Id);
}
return Ok();
}
else
{
return Conflict(CommunicationErrors.Common_Entity_Changed);
}
}
else
{
return Conflict(CommunicationErrors.Common_Relation_Changed);
}
}
return NotFound(CommunicationErrors.Common_NotFound);
}
return BadRequest(CommunicationErrors.Common_Model_Invalid);
}
return NotFound(CommunicationErrors.Common_NotFound);
}
///
/// Abfrage der Walks eines AppUsers
///
/// Id des AppUsers
/// Letztes Update oder null, wenn noch keines
/// Liste der Anfragen
[HttpGet]
[Route("GetWalksForSync")]
public async Task GetWalksForSync(string appUserId, DateTimeOffset? lastUpdate)
{
var clientOffset = GetClientDateOffset();
if (User?.Identity != null && User.Identity.IsAuthenticated)
{
var requests = await _walkService.GetForSyncAppAsync(appUserId, lastUpdate);
var dtoList = Mapper.Map>(requests);
return Ok(dtoList);
}
return NotFound(CommunicationErrors.Common_NotFound);
}
///
/// Anlegen eines Walks
///
/// WalkDto
/// HTTP 200 OK, Felher sonst
[HttpPost]
[Route("CreateWalk")]
public async Task CreateWalk(WalkDto model)
{
var clientOffset = GetClientDateOffset();
var result = new CreateResponseDto
{
Status = CreateStatusDto.Error,
Value = null
};
if (User?.Identity != null && User.Identity.IsAuthenticated)
{
if (ModelState.IsValid)
{
var existing = await _walkService.GetAsync(model.Id);
if (existing == null)
{
var walk = Mapper.Map(model);
_walkService.Add(walk);
await _walkService.CommitAsync(User.Identity.Name);
result.Status = CreateStatusDto.Success;
result.Value = Mapper.Map(walk);
}
else
{
result.Status = CreateStatusDto.Exists;
}
return Ok(result);
}
}
return BadRequest(CommunicationErrors.Common_Model_Invalid);
}
///
/// Aktualisieren eines Walks
///
/// WalkDto
/// HTTP 200 OK, Felher sonst
[HttpPost]
[Route("UpdateWalk")]
public async Task UpdateWalk(WalkDto model)
{
var clientOffset = GetClientDateOffset();
if (User?.Identity != null && User.Identity.IsAuthenticated)
{
if (ModelState.IsValid)
{
var walk = await _walkService.GetAsync(model.Id);
if (walk != null)
{
//TODO: muss hier noch auf den Wechsel diverser Stati reagiert werden?
if (model.UpdatedAt > walk.UpdatedAt)
{
Mapper.Map(model, walk);
await _walkService.CommitAsync(User.Identity.Name);
}
return Ok();
}
return NotFound(CommunicationErrors.Common_NotFound);
}
return BadRequest(CommunicationErrors.Common_Model_Invalid);
}
return NotFound(CommunicationErrors.Common_NotFound);
}
///
/// Löschen eines Walks
///
/// WalkDto
/// Id des App-Users
/// 200OK
[HttpPost]
[Route("DeleteWalk")]
public async Task DeleteWalk(WalkDto model, [FromQuery] string appUserId)
{
var clientOffset = GetClientDateOffset();
if (User?.Identity != null && User.Identity.IsAuthenticated)
{
if (ModelState.IsValid)
{
var walk = await _walkService.GetAsync(model.Id);
if (walk != null)
{
var appUser = await AppUserService.GetAsync(appUserId);
if (appUser != null)
{
if (walk.DogOwnerId == appUser.Id)
{
//TODO: Löschen von verbundenen Daten!
_walkService.Remove(walk);
await _walkService.CommitAsync(User.Identity.Name);
return Ok();
}
}
}
return NotFound(CommunicationErrors.Common_NotFound);
}
return BadRequest(CommunicationErrors.Common_Model_Invalid);
}
return NotFound(CommunicationErrors.Common_NotFound);
}
///
/// Abfragen von Walks - wird eigentlich nur von Hundebesitzern aufgerufen
///
/// Abfragemodel
/// Liste von Walks
[HttpPost]
[Route("GetWalks")]
public async Task GetWalks(WalksQueryDto model)
{
var clientOffset = GetClientDateOffset();
if (User?.Identity != null && User.Identity.IsAuthenticated)
{
var baseAddress = GetBaseAddress();
var response = new ListResponseDto();
//Geodaten holen.
//Entweder wurde lat und lng geliefert, oder wir müssen über den benutzer und den app-mode entscheiden
//var (country, state) = await GetGeoDataAsync(model);
var sortList = Mapper.Map>(model.DynamicSortOrder);
var queryResult = await _walkService.GetWithNamesAsync(model.DogWalkerId, model.DogOwnerId, model.Date, (WalkStatus?)model.Status, (WalkServiceType?)model.ServiceType, (PaymentStatus?)model.PaymentStatus, model.DogFilter, model.WalkerFilter, model.OwnerFilter, model.IgnoreCancelled, model.ForNextWalk, model.IgnoreRequested, model.IgnoreDeclined, sortList, model.Location.Lat.Value, model.Location.Lng.Value, model.Skip, model.Take);
response.Total = queryResult.total;
var resultList = queryResult.list;
foreach (var walk in resultList)
{
walk.Dogs = new List();
if (!string.IsNullOrWhiteSpace(walk.DogsJson))
{
var dogsList = JsonSerializer.Deserialize>(walk.DogsJson, new JsonSerializerOptions(JsonSerializerDefaults.Web));
foreach (var dogItem in dogsList)
{
var dog = await _dogService.GetWithNamesAsync(dogItem.Id, model.Language, LocalizationOptions.Value.DefaultCulture, true);
if (dog != null)
{
walk.Dogs.Add(new DogMinInfo()
{
Id = dog.Id,
Index = dog.Index,
Version = dog.Version,
UpdatedAt = dog.UpdatedAt,
Deleted = dog.Deleted,
DogRaceId = dog.DogRaceId,
DogRaceName = dog.DogRaceName,
Name = dog.Name,
Photo = !string.IsNullOrWhiteSpace(dog.Photo) ? $"{baseAddress}/file/documents/thumbnails/{200}/{dog.Photo}" : string.Empty,
Sex = dog.Sex,
Size = dog.Size,
BirthDate = dog.BirthDate,
AverageRating = dog.RatingStatistics_AverageRating
});
}
}
}
}
var dtoList = Mapper.Map>(resultList);
foreach (var dtoItem in dtoList)
{
if (!string.IsNullOrWhiteSpace(dtoItem.DogOwnerPhoto))
dtoItem.DogOwnerPhoto = $"{baseAddress}/file/documents/thumbnails/{200}/{dtoItem.DogOwnerPhoto}";
if (!string.IsNullOrWhiteSpace(dtoItem.DogWalkerPhoto))
dtoItem.DogWalkerPhoto = $"{baseAddress}/file/documents/thumbnails/{200}/{dtoItem.DogWalkerPhoto}";
}
response.List = dtoList;
response.Take = model.Take;
response.Skip = model.Skip;
return Ok(response);
}
return NotFound(CommunicationErrors.Common_NotFound);
}
///
/// Abfragen von Walks für einen Walker.
/// Sondersituation: Walker bekommen keine Walks mit einem PaymentStatus unter Authorized zurück
///
/// Abfragemodel
/// Liste von Walks
[HttpPost]
[Route("GetWalksWalker")]
public async Task GetWalksWalker(WalksQueryDto model)
{
var clientOffset = GetClientDateOffset();
if (User?.Identity != null && User.Identity.IsAuthenticated)
{
var baseAddress = GetBaseAddress();
var response = new ListResponseDto();
//Geodaten holen.
//Entweder wurde lat und lng geliefert, oder wir müssen über den benutzer und den app-mode entscheiden
//var (country, state) = await GetGeoDataAsync(model);
var sortList = Mapper.Map>(model.DynamicSortOrder);
var queryResult = await _walkService.GetWithNamesForWalkerAsync(model.DogWalkerId, model.DogOwnerId, model.Date, (WalkStatus?)model.Status, (WalkServiceType?)model.ServiceType, (PaymentStatus?)model.PaymentStatus, model.DogFilter, model.WalkerFilter, model.OwnerFilter, model.IgnoreCancelled, model.ForNextWalk, model.IgnoreRequested, model.IgnoreDeclined, sortList, model.Location.Lat.Value, model.Location.Lng.Value, model.Skip, model.Take);
response.Total = queryResult.total;
var resultList = queryResult.list;
foreach (var walk in resultList)
{
walk.Dogs = new List();
if (!string.IsNullOrWhiteSpace(walk.DogsJson))
{
var dogsList = JsonSerializer.Deserialize>(walk.DogsJson, new JsonSerializerOptions(JsonSerializerDefaults.Web));
foreach (var dogItem in dogsList)
{
var dog = await _dogService.GetWithNamesAsync(dogItem.Id, model.Language, LocalizationOptions.Value.DefaultCulture, true);
if (dog != null)
{
walk.Dogs.Add(new DogMinInfo()
{
Id = dog.Id,
Index = dog.Index,
Version = dog.Version,
UpdatedAt = dog.UpdatedAt,
Deleted = dog.Deleted,
DogRaceId = dog.DogRaceId,
DogRaceName = dog.DogRaceName,
Name = dog.Name,
Photo = !string.IsNullOrWhiteSpace(dog.Photo) ? $"{baseAddress}/file/documents/thumbnails/{200}/{dog.Photo}" : string.Empty,
Sex = dog.Sex,
Size = dog.Size,
BirthDate = dog.BirthDate,
AverageRating = dog.RatingStatistics_AverageRating
});
}
else
{
walk.Dogs.Add(new DogMinInfo()
{
Id = dogItem.Id,
Index = 0,
Version = null,
UpdatedAt = DateTimeOffset.UtcNow,
Deleted = false,
DogRaceId = string.Empty,
DogRaceName = string.Empty,
Name = dogItem.Name,
Photo = string.Empty,
AverageRating = 0,
Sex = DogSex.MaleDog,
Size = DogSize.Middle
});
}
}
}
}
var dtoList = Mapper.Map>(resultList);
var appUserId = User.AppUserId();
foreach (var dtoItem in dtoList)
{
if (!string.IsNullOrWhiteSpace(dtoItem.DogOwnerPhoto))
dtoItem.DogOwnerPhoto = $"{baseAddress}/file/documents/thumbnails/{200}/{dtoItem.DogOwnerPhoto}";
if (!string.IsNullOrWhiteSpace(dtoItem.DogWalkerPhoto))
dtoItem.DogWalkerPhoto = $"{baseAddress}/file/documents/thumbnails/{200}/{dtoItem.DogWalkerPhoto}";
dtoItem.Locked = await AppUserService.IsLockedAsync(dtoItem.DogOwnerId);
dtoItem.Blocked = await AppUserService.IsBlockedAsync(appUserId, dtoItem.DogOwnerId);
}
response.List = dtoList;
response.Take = model.Take;
response.Skip = model.Skip;
return Ok(response);
}
return NotFound(CommunicationErrors.Common_NotFound);
}
///
/// Gibt eine Liste der nächsten Walks, laufende, nicht abgeschlossene, nicht bezahlte usw. für einen Hundebesitzer zurück.
/// Aktuell laufender Walk
/// Nicht gestartete Walks
/// Zu bezahlende Walks
/// Nicht abgeschlossene Walks
/// Nächster anstehender Walk
///
/// WalksNextQueryDto
/// Liste von Walks
[HttpPost]
[Route("GetNextWalksOwner")]
public async Task GetNextWalksOwner(WalksNextQueryDto model)
{
var clientOffset = GetClientDateOffset();
if (User?.Identity != null && User.Identity.IsAuthenticated)
{
var baseAddress = GetBaseAddress();
var response = new ListResponseDto();
var queryResult = await _walkService.GetNextWithNamesForOwnerAsync(model.AppUserId, model.Date, model.Skip, model.Take);
response.Total = queryResult.total;
var resultList = queryResult.list;
foreach (var walk in resultList)
{
walk.Dogs = new List();
if (!string.IsNullOrWhiteSpace(walk.DogsJson))
{
var dogsList = JsonSerializer.Deserialize>(walk.DogsJson, new JsonSerializerOptions(JsonSerializerDefaults.Web));
foreach (var dogItem in dogsList)
{
var dog = await _dogService.GetWithNamesAsync(dogItem.Id, model.Language, LocalizationOptions.Value.DefaultCulture, true);
if (dog != null)
{
walk.Dogs.Add(new DogMinInfo()
{
Id = dog.Id,
Index = dog.Index,
Version = dog.Version,
UpdatedAt = dog.UpdatedAt,
Deleted = dog.Deleted,
DogRaceId = dog.DogRaceId,
DogRaceName = dog.DogRaceName,
Name = dog.Name,
Photo = !string.IsNullOrWhiteSpace(dog.Photo) ? $"{baseAddress}/file/documents/thumbnails/{200}/{dog.Photo}" : string.Empty,
Sex = dog.Sex,
Size = dog.Size,
BirthDate = dog.BirthDate,
AverageRating = dog.RatingStatistics_AverageRating
});
}
}
}
}
var dtoList = Mapper.Map>(resultList);
foreach (var dtoItem in dtoList)
{
if (!string.IsNullOrWhiteSpace(dtoItem.DogOwnerPhoto))
dtoItem.DogOwnerPhoto = $"{baseAddress}/file/documents/thumbnails/{200}/{dtoItem.DogOwnerPhoto}";
if (!string.IsNullOrWhiteSpace(dtoItem.DogWalkerPhoto))
dtoItem.DogWalkerPhoto = $"{baseAddress}/file/documents/thumbnails/{200}/{dtoItem.DogWalkerPhoto}";
}
response.List = dtoList;
response.Take = model.Take;
response.Skip = model.Skip;
return Ok(response);
}
return NotFound(CommunicationErrors.Common_NotFound);
}
///
/// Gibt eine Liste der nächsten Walks, laufende, nicht abgeschlossene, nicht bezahlte usw. für einen Dogwalker zurück.
/// Aktuell laufender Walk
/// Nicht gestartete Walks
/// Nicht abgeschlossene Walks
/// Nächster anstehender Walk
///
/// WalksNextQueryDto
/// Liste von Walks
[HttpPost]
[Route("GetNextWalksWalker")]
public async Task GetNextWalksWalker(WalksNextQueryDto model)
{
var clientOffset = GetClientDateOffset();
if (User?.Identity != null && User.Identity.IsAuthenticated)
{
var baseAddress = GetBaseAddress();
var response = new ListResponseDto();
var queryResult = await _walkService.GetNextWithNamesForWalkerAsync(model.AppUserId, model.Date, model.Skip, model.Take);
response.Total = queryResult.total;
var resultList = queryResult.list;
foreach (var walk in resultList)
{
walk.Dogs = new List();
if (!string.IsNullOrWhiteSpace(walk.DogsJson))
{
var dogsList = JsonSerializer.Deserialize>(walk.DogsJson, new JsonSerializerOptions(JsonSerializerDefaults.Web));
foreach (var dogItem in dogsList)
{
var dog = await _dogService.GetWithNamesAsync(dogItem.Id, model.Language, LocalizationOptions.Value.DefaultCulture, true);
if (dog != null)
{
walk.Dogs.Add(new DogMinInfo()
{
Id = dog.Id,
Index = dog.Index,
Version = dog.Version,
UpdatedAt = dog.UpdatedAt,
Deleted = dog.Deleted,
DogRaceId = dog.DogRaceId,
DogRaceName = dog.DogRaceName,
Name = dog.Name,
Photo = !string.IsNullOrWhiteSpace(dog.Photo) ? $"{baseAddress}/file/documents/thumbnails/{200}/{dog.Photo}" : string.Empty,
Sex = dog.Sex,
Size = dog.Size,
BirthDate = dog.BirthDate,
AverageRating = dog.RatingStatistics_AverageRating
});
}
else
{
walk.Dogs.Add(new DogMinInfo()
{
Id = dogItem.Id,
Index = 0,
Version = null,
UpdatedAt = DateTimeOffset.UtcNow,
Deleted = false,
DogRaceId = string.Empty,
DogRaceName = string.Empty,
Name = dogItem.Name,
Photo = string.Empty,
AverageRating = 0,
Sex = DogSex.MaleDog,
Size = DogSize.Middle
});
}
}
}
}
var dtoList = Mapper.Map>(resultList);
var appUserId = User.AppUserId();
foreach (var dtoItem in dtoList)
{
if (!string.IsNullOrWhiteSpace(dtoItem.DogOwnerPhoto))
dtoItem.DogOwnerPhoto = $"{baseAddress}/file/documents/thumbnails/{200}/{dtoItem.DogOwnerPhoto}";
if (!string.IsNullOrWhiteSpace(dtoItem.DogWalkerPhoto))
dtoItem.DogWalkerPhoto = $"{baseAddress}/file/documents/thumbnails/{200}/{dtoItem.DogWalkerPhoto}";
dtoItem.Locked = await AppUserService.IsLockedAsync(dtoItem.DogOwnerId);
dtoItem.Blocked = await AppUserService.IsBlockedAsync(appUserId, dtoItem.DogOwnerId);
}
response.List = dtoList;
response.Take = model.Take;
response.Skip = model.Skip;
return Ok(response);
}
return NotFound(CommunicationErrors.Common_NotFound);
}
///
/// Gibt einen Walk mit Namen zurück
///
/// Id des Walks
/// Gewünschte Sprache
/// Walk
[HttpGet]
[Route("GetWalkWithNames")]
public async Task GetWalkWithNames(string walkId, string language)
{
var clientOffset = GetClientDateOffset();
if (User?.Identity != null && User.Identity.IsAuthenticated)
{
var walk = await _walkService.GetWalkWithNamesAsync(walkId);
var walkDto = Mapper.Map(walk);
var baseAddress = GetBaseAddress();
var appUserId = User.AppUserId();
var targetUserId = walk.DogOwnerId == appUserId ? walk.DogWalkerId : walk.DogOwnerId;
var isLocked = await AppUserService.IsLockedAsync(targetUserId);
var isBlocked = await AppUserService.IsBlockedAsync(appUserId, targetUserId);
walkDto.Dogs = new List();
if (!string.IsNullOrWhiteSpace(walk.DogsJson))
{
var dogsList = JsonSerializer.Deserialize>(walk.DogsJson, new JsonSerializerOptions(JsonSerializerDefaults.Web));
foreach (var dogItem in dogsList)
{
var dog = await _dogService.GetWithNamesAsync(dogItem.Id, language, LocalizationOptions.Value.DefaultCulture, true);
if (dog != null)
{
walkDto.Dogs.Add(new DogMinInfoDto()
{
Id = dog.Id,
Version = dog.Version,
UpdatedAt = dog.UpdatedAt,
Deleted = dog.Deleted,
DogRaceId = dog.DogRaceId,
DogRaceName = dog.DogRaceName,
Size = (DogSizeDto)dog.Size,
Sex = (DogSexDto)dog.Sex,
Name = dog.Name,
BirthDate = dog.BirthDate,
Photo = !string.IsNullOrWhiteSpace(dog.Photo) ? $"{baseAddress}/file/documents/thumbnails/{400}/{dog.Photo}" : string.Empty,
AverageRating = dog.RatingStatistics_AverageRating,
TotalRatings = dog.RatingStatistics_TotalRatings,
Locked = isLocked,
Blocked = isBlocked
});
}
}
}
if (!string.IsNullOrWhiteSpace(walkDto.DogOwnerPhoto))
walkDto.DogOwnerPhoto = $"{baseAddress}/file/documents/thumbnails/{400}/{walkDto.DogOwnerPhoto}";
if (!string.IsNullOrWhiteSpace(walkDto.DogWalkerPhoto))
walkDto.DogWalkerPhoto = $"{baseAddress}/file/documents/thumbnails/{400}/{walkDto.DogWalkerPhoto}";
walkDto.Locked = isLocked;
walkDto.Blocked = isBlocked;
return Ok(walkDto);
}
return NotFound(CommunicationErrors.Common_NotFound);
}
///
/// Gibt einen Walk zurück der mit einer öffentlichen Anfrage verknüpft ist
///
/// Id der öffentlichen Anfrage
/// Walk
[HttpGet]
[Route("GetWalkByPublicRequest")]
public async Task GetWalkByPublicRequest(string publicWalkRequestId)
{
var clientOffset = GetClientDateOffset();
if (User?.Identity != null && User.Identity.IsAuthenticated)
{
var walk = await _walkService.GetWalkByPublicRequestAsync(publicWalkRequestId);
if (walk != null)
{
var walkDto = Mapper.Map(walk);
return Ok(walkDto);
}
}
return NotFound(CommunicationErrors.Common_NotFound);
}
///
/// Stornieren eines Walks
///
/// PublicWalkRequestCancelDto
/// HTTP 200 OK, Fehler sonst
[HttpPost]
[Route("CancelWalk")]
public async Task CancelWalk(WalkCancelDto model)
{
var clientOffset = GetClientDateOffset();
if (User?.Identity != null && User.Identity.IsAuthenticated)
{
if (ModelState.IsValid)
{
var walk = await _walkService.GetAsync(model.WalkId);
if (walk != null)
{
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.UpdatedAt = model.UpdatedAt;
walk.CancelledBy = (CancellationSource)model.CancellationSource;
walk.CancelledReason = model.CancelledReason;
//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 _walkService.CommitAsync(User.Identity.Name);
//Wallets aktualisieren
await _mangoPayService.GetWalletBalanceAsync(walk.DogOwnerId, WalletType.Credits);
await _mangoPayService.GetWalletBalanceAsync(walk.DogOwnerId, WalletType.Fees);
if (walk.CancelledBy == CancellationSource.DogWalker)
{
_systemMessageService.Add(walk.DogOwnerId, AppUserType.DogOwner, walk.Id, SystemMessageTables.Walk, SystemMessageType.WalkCancelled, DateTimeOffset.UtcNow.AddDays(14));
await _systemMessageService.CommitAsync(User.Identity.Name);
await _appHubSender.SystemMessageAddedAsync(walk.DogOwnerId);
await _pushNotificationService.SendWalkCancelledAsync(walk.DogOwnerId, walk.Id, AppMode.DogOwner);
}
else
{
_systemMessageService.Add(walk.DogWalkerId, AppUserType.DogWalker, walk.Id, SystemMessageTables.Walk, SystemMessageType.WalkCancelled, DateTimeOffset.UtcNow.AddDays(14));
await _systemMessageService.CommitAsync(User.Identity.Name);
await _appHubSender.SystemMessageAddedAsync(walk.DogWalkerId);
await _pushNotificationService.SendWalkCancelledAsync(walk.DogWalkerId, walk.Id, AppMode.DogWalker);
}
return Ok();
}
return NotFound(CommunicationErrors.Common_NotFound);
}
return BadRequest(CommunicationErrors.Common_Model_Invalid);
}
return NotFound(CommunicationErrors.Common_NotFound);
}
///
/// Starten eines Walks
///
/// PublicWalkRequestCancelDto
/// HTTP 200 OK, Felher sonst
[HttpPost]
[Route("StartWalk")]
public async Task StartWalk(WalkStartDto model)
{
var clientOffset = GetClientDateOffset();
if (User?.Identity != null && User.Identity.IsAuthenticated)
{
if (ModelState.IsValid)
{
var walk = await _walkService.GetAsync(model.WalkId);
if (walk != null)
{
walk.Status = WalkStatus.Started;
walk.Started = model.UpdatedAt;
walk.UpdatedAt = model.UpdatedAt;
await _walkService.CommitAsync(User.Identity.Name);
_systemMessageService.Add(walk.DogOwnerId, AppUserType.DogOwner, walk.Id, SystemMessageTables.Walk, SystemMessageType.WalkStarted, DateTimeOffset.UtcNow.AddDays(14));
await _systemMessageService.CommitAsync(User.Identity.Name);
await _appHubSender.SystemMessageAddedAsync(walk.DogOwnerId);
await _pushNotificationService.SendWalkStartedAsync(walk.DogOwnerId, walk.Id);
return Ok();
}
return NotFound(CommunicationErrors.Common_NotFound);
}
return BadRequest(CommunicationErrors.Common_Model_Invalid);
}
return NotFound(CommunicationErrors.Common_NotFound);
}
///
/// abschließen eines Walks - Alte Version mit Bewertung von Walk.
/// Wird durch CompleteWalkEx ersetzt, welches die Bewertung des Hundebesitzers implementiert
///
/// WalkCompleteDto
/// HTTP 200 OK, Felher sonst
[HttpPost]
[Route("CompleteWalk")]
public async Task CompleteWalk(WalkCompleteDto model)
{
var clientOffset = GetClientDateOffset();
if (User?.Identity != null && User.Identity.IsAuthenticated)
{
if (ModelState.IsValid)
{
var walk = await _walkService.GetAsync(model.WalkId);
if (walk != null)
{
if (walk.Status < WalkStatus.Completed)
{
walk.Status = WalkStatus.Completed;
walk.Completed = model.UpdatedAt;
walk.UpdatedAt = model.UpdatedAt;
walk.CompletedInfo = model.CompletedInfo;
walk.Defactation = model.Defactation;
await _walkService.CommitAsync(User.Identity.Name);
_systemMessageService.Add(walk.DogOwnerId, AppUserType.DogOwner, walk.Id, SystemMessageTables.Walk, SystemMessageType.WalkCompleted, DateTimeOffset.UtcNow.AddDays(14));
await _systemMessageService.CommitAsync(User.Identity.Name);
await _appHubSender.SystemMessageAddedAsync(walk.DogOwnerId);
await _pushNotificationService.SendWalkCompletedAsync(walk.DogOwnerId, walk.Id);
//Rating erstellen
var appUser = await AppUserService.GetAsync(walk.DogWalkerId);
if (appUser != null)
{
var ratingTargetType = walk.ServiceType switch
{
WalkServiceType.Sitting => RatingTarget.Sitting,
WalkServiceType.DayCare => RatingTarget.DayCare,
_ => RatingTarget.Walk
};
var rating = _ratingService.Create(walk.DogWalkerId, appUser.Type, walk.Id, ratingTargetType, model.RatingPoints, model.RatingInfo);
_ratingService.Add(rating);
//Neu: Rating für jeden der Hunde erstellen wenn es mehrere sind, oder halt einen wenn nur einer ist
if (model.RatingDogsPoints != null && model.RatingDogsPoints >= 0)
{
var dogsList = JsonSerializer.Deserialize>(walk.DogsJson, new JsonSerializerOptions(JsonSerializerDefaults.Web));
foreach (var dogWalkJson in dogsList)
{
var ratingDog = _ratingService.Create(walk.DogWalkerId, appUser.Type, dogWalkJson.Id, RatingTarget.Dog, model.RatingDogsPoints, model.RatingDogsInfo);
_ratingService.Add(ratingDog);
}
}
await _ratingService.CommitAsync(User.Identity.Name);
//Rating-Statistik für Hunde / Hunde aktualisieren
if (model.RatingDogsPoints != null && model.RatingDogsPoints >= 0)
{
var dogsList = JsonSerializer.Deserialize>(walk.DogsJson, new JsonSerializerOptions(JsonSerializerDefaults.Web));
foreach (var dogWalkJson in dogsList)
{
await _ratingService.UpdateRatingStatisticsAsync(dogWalkJson.Id, RatingTarget.Dog);
}
await _ratingService.CommitAsync(User.Identity.Name);
}
}
}
return Ok();
}
return NotFound(CommunicationErrors.Common_NotFound);
}
return BadRequest(CommunicationErrors.Common_Model_Invalid);
}
return NotFound(CommunicationErrors.Common_NotFound);
}
///
/// Abschließen eines Walks - mit Bewertung Hundebesitzer anstatt des Walks
///
/// WalkCompleteDto
/// HTTP 200 OK, Felher sonst
[HttpPost]
[Route("CompleteWalkEx")]
public async Task CompleteWalkEx(WalkCompleteDto model)
{
var clientOffset = GetClientDateOffset();
if (User?.Identity != null && User.Identity.IsAuthenticated)
{
if (ModelState.IsValid)
{
var walk = await _walkService.GetAsync(model.WalkId);
if (walk != null)
{
if (walk.Status < WalkStatus.Completed)
{
walk.Status = WalkStatus.Completed;
walk.Completed = model.UpdatedAt;
walk.UpdatedAt = model.UpdatedAt;
walk.CompletedInfo = model.CompletedInfo;
walk.Defactation = model.Defactation;
await _walkService.CommitAsync(User.Identity.Name);
_systemMessageService.Add(walk.DogOwnerId, AppUserType.DogOwner, walk.Id, SystemMessageTables.Walk, SystemMessageType.WalkCompleted, DateTimeOffset.UtcNow.AddDays(14));
await _systemMessageService.CommitAsync(User.Identity.Name);
await _appHubSender.SystemMessageAddedAsync(walk.DogOwnerId);
await _pushNotificationService.SendWalkCompletedAsync(walk.DogOwnerId, walk.Id);
//Rating erstellen
var appUser = await AppUserService.GetAsync(walk.DogWalkerId);
if (appUser != null)
{
var rating = _ratingService.Create(walk.DogWalkerId, appUser.Type, walk.DogOwnerId, RatingTarget.Owner, model.RatingPoints, model.RatingInfo);
_ratingService.Add(rating);
//Neu: Rating für jeden der Hunde erstellen wenn es mehrere sind, oder halt einen wenn nur einer ist
if (model.RatingDogsPoints != null && model.RatingDogsPoints >= 0)
{
var dogsList = JsonSerializer.Deserialize>(walk.DogsJson, new JsonSerializerOptions(JsonSerializerDefaults.Web));
foreach (var dogWalkJson in dogsList)
{
var ratingDog = _ratingService.Create(walk.DogWalkerId, appUser.Type, dogWalkJson.Id, RatingTarget.Dog, model.RatingDogsPoints, model.RatingDogsInfo);
_ratingService.Add(ratingDog);
}
}
await _ratingService.CommitAsync(User.Identity.Name);
//Statistik Hundebesitzer aktualisieren
await _ratingService.UpdateRatingStatisticsAsync(walk.DogOwnerId, RatingTarget.Owner);
//Rating-Statistik für Hunde / Hunde aktualisieren
if (model.RatingDogsPoints != null && model.RatingDogsPoints >= 0)
{
var dogsList = JsonSerializer.Deserialize>(walk.DogsJson, new JsonSerializerOptions(JsonSerializerDefaults.Web));
foreach (var dogWalkJson in dogsList)
{
await _ratingService.UpdateRatingStatisticsAsync(dogWalkJson.Id, RatingTarget.Dog);
}
}
await _ratingService.CommitAsync(User.Identity.Name);
}
}
return Ok();
}
return NotFound(CommunicationErrors.Common_NotFound);
}
return BadRequest(CommunicationErrors.Common_Model_Invalid);
}
return NotFound(CommunicationErrors.Common_NotFound);
}
///
/// Bestätigen eines Walks
///
/// WalkConfirmDto
/// HTTP 200 OK, Felher sonst
[HttpPost]
[Route("ConfirmWalk")]
public async Task ConfirmWalk(WalkConfirmDto model)
{
var clientOffset = GetClientDateOffset();
if (User?.Identity != null && User.Identity.IsAuthenticated)
{
if (ModelState.IsValid)
{
var walk = await _walkService.GetAsync(model.WalkId);
if (walk != null && walk.DogOwnerId == model.AppUserId)
{
var appUser = await AppUserService.GetAsync(walk.DogOwnerId);
if (appUser is { Locked: true })
{
return BadRequest(CommunicationErrors.Login_LockedOut);
}
var dogWalker = await AppUserService.GetAsync(walk.DogWalkerId);
if (dogWalker is { Locked: true })
{
return BadRequest(CommunicationErrors.Login_LockedOut);
}
if (walk.Status == WalkStatus.Completed && walk.Deleted == false)
{
walk.Status = WalkStatus.Confirmed;
walk.Confirmed = DateTimeOffset.UtcNow;
walk.UpdatedAt = DateTimeOffset.UtcNow;
walk.PaymentStatus = PaymentStatus.Paid;
await _walkService.CommitAsync(User.Identity.Name);
//Wenn der Dogwalker in 30 Minuten mehr als 4 Walks bestätigt bekommt, dann Sperren wegen Betrugsverdacht
var numberOfConfirmedWalksTwentyMinutes = await _walkService.CountConfirmedByTimeRangeAsync(walk.DogWalkerId, DateTimeOffset.UtcNow.AddMinutes(-30), DateTimeOffset.UtcNow);
if (numberOfConfirmedWalksTwentyMinutes >= 4)
{
if (dogWalker != null)
{
dogWalker.Locked = true;
dogWalker.LockedReason = "Suspicious behavior - verächtiges Verhalten";
dogWalker.LockedUntil = DateTimeOffset.UtcNow.AddYears(5);
await AppUserService.CommitAsync("System");
//Echten Benutzer sperren
var user = await _userService.GetByAppUserAsync(dogWalker.Id);
if (user != null)
{
user.LockoutEnd = DateTimeOffset.UtcNow.AddYears(5);
await _userService.CommitAsync("System");
await _ticketStore.RemoveAsync(user.UserName);
await _refreshTokenService.RemoveAllAsync(user.Id, User.Identity.Name);
await _refreshTokenService.CommitAsync("System");
}
}
}
//Zahlung veranlassen....
if (walk.Price > 0)
{
decimal feeDecimal = 0;
long fee = 0;
var gehGassiFee = await _transactionFeeService.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)
{
fee = (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 _voucherCampaignService.CommitAsync(User.Identity.Name);
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, fee, $"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);
}
}
}
//Coins für den Walker gutschreiben
var coins = walk.ServiceType switch
{
WalkServiceType.Walking => _coinsOptions.Value.WalkForDogwalker,
WalkServiceType.Sitting => _coinsOptions.Value.SittingForDowgWalker,
WalkServiceType.DayCare => _coinsOptions.Value.DayCareForDowgWalker,
_ => 0m
};
await _coinsService.DepositAsync(walk.DogWalkerId, AppUserType.DogWalker, coins, walk.Id);
//Coins für den Besitzer gutschreiben
var coinsOwner = walk.ServiceType switch
{
WalkServiceType.Walking => _coinsOptions.Value.WalkForOwner,
WalkServiceType.Sitting => _coinsOptions.Value.SittingForOwner,
WalkServiceType.DayCare => _coinsOptions.Value.DayCareForOwner,
_ => 0m
};
await _coinsService.DepositAsync(walk.DogOwnerId, AppUserType.DogOwner, coinsOwner, walk.Id);
_systemMessageService.Add(walk.DogWalkerId, AppUserType.DogWalker, walk.Id, SystemMessageTables.Walk, SystemMessageType.WalkConfirmed, DateTimeOffset.UtcNow.AddDays(14));
await _systemMessageService.CommitAsync(User.Identity.Name);
await _appHubSender.SystemMessageAddedAsync(walk.DogWalkerId);
await _pushNotificationService.SendWalkConfirmedAsync(walk.DogWalkerId, walk.Id);
var walkDto = Mapper.Map(walk);
return Ok(walkDto);
}
}
return NotFound(CommunicationErrors.Common_NotFound);
}
return BadRequest(CommunicationErrors.Common_Model_Invalid);
}
return NotFound(CommunicationErrors.Common_NotFound);
}
///
/// Bestätigen eines Walks mit Rating
///
/// WalkConfirmDto
/// HTTP 200 OK, Felher sonst
[HttpPost]
[Route("ConfirmWalkWithRating")]
public async Task ConfirmWalkWithRating(WalkConfirmWithRatingDto model)
{
var clientOffset = GetClientDateOffset();
if (User?.Identity != null && User.Identity.IsAuthenticated)
{
if (ModelState.IsValid)
{
var walk = await _walkService.GetAsync(model.WalkId);
if (walk != null && walk.DogOwnerId == model.AppUserId)
{
var appUser = await AppUserService.GetAsync(walk.DogOwnerId);
if (appUser is { Locked: true })
{
return BadRequest(CommunicationErrors.Login_LockedOut);
}
var dogWalker = await AppUserService.GetAsync(walk.DogWalkerId);
if (dogWalker is { Locked: true })
{
return BadRequest(CommunicationErrors.Login_LockedOut);
}
if (walk.Status == WalkStatus.Completed && walk.Deleted == false)
{
walk.Status = WalkStatus.Confirmed;
walk.Confirmed = DateTimeOffset.UtcNow;
walk.UpdatedAt = DateTimeOffset.UtcNow;
walk.PaymentStatus = PaymentStatus.Paid;
await _walkService.CommitAsync(User.Identity.Name);
//Wenn der Dogwalker in 30 Minuten mehr als 4 Walks bestätigt bekommt, dann Sperren wegen Betrugsverdacht
var numberOfConfirmedWalksTwentyMinutes = await _walkService.CountConfirmedByTimeRangeAsync(walk.DogWalkerId, DateTimeOffset.UtcNow.AddMinutes(-30), DateTimeOffset.UtcNow);
if (numberOfConfirmedWalksTwentyMinutes >= 4)
{
if (dogWalker != null)
{
dogWalker.Locked = true;
dogWalker.LockedReason = "Suspicious behavior - verächtiges Verhalten";
dogWalker.LockedUntil = DateTimeOffset.UtcNow.AddYears(5);
await AppUserService.CommitAsync("System");
//Echten Benutzer sperren
var user = await _userService.GetByAppUserAsync(dogWalker.Id);
if (user != null)
{
user.LockoutEnd = DateTimeOffset.UtcNow.AddYears(5);
await _userService.CommitAsync("System");
await _ticketStore.RemoveAsync(user.UserName);
await _refreshTokenService.RemoveAllAsync(user.Id, User.Identity.Name);
await _refreshTokenService.CommitAsync("System");
}
}
}
//Zahlung veranlassen....
if (walk.Price > 0)
{
decimal feeDecimal = 0;
long fee = 0;
var gehGassiFee = await _transactionFeeService.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)
{
fee = (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 _voucherCampaignService.CommitAsync(User.Identity.Name);
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, fee, $"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);
}
}
}
//Coins für den Walker gutschreiben
var coins = walk.ServiceType switch
{
WalkServiceType.Walking => _coinsOptions.Value.WalkForDogwalker,
WalkServiceType.Sitting => _coinsOptions.Value.SittingForDowgWalker,
WalkServiceType.DayCare => _coinsOptions.Value.DayCareForDowgWalker,
_ => 0m
};
await _coinsService.DepositAsync(walk.DogWalkerId, AppUserType.DogWalker, coins, walk.Id);
//Coins für den Besitzer gutschreiben
var coinsOwner = walk.ServiceType switch
{
WalkServiceType.Walking => _coinsOptions.Value.WalkForOwner,
WalkServiceType.Sitting => _coinsOptions.Value.SittingForOwner,
WalkServiceType.DayCare => _coinsOptions.Value.DayCareForOwner,
_ => 0m
};
await _coinsService.DepositAsync(walk.DogOwnerId, AppUserType.DogOwner, coinsOwner, walk.Id);
//Rating erstellen
//var appUser = await AppUserService.GetAsync(walk.DogOwnerId);
if (appUser != null)
{
var rating = _ratingService.Create(walk.DogOwnerId, appUser.Type, walk.DogWalkerId, RatingTarget.Walker, model.RatingPoints, model.RatingInfo);
_ratingService.Add(rating);
await _ratingService.CommitAsync(User.Identity.Name);
//Statistik Hundebesitzer aktualisieren
await _ratingService.UpdateRatingStatisticsAsync(walk.DogWalkerId, RatingTarget.Walker);
await _ratingService.CommitAsync(User.Identity.Name);
}
_systemMessageService.Add(walk.DogWalkerId, AppUserType.DogWalker, walk.Id, SystemMessageTables.Walk, SystemMessageType.WalkConfirmed, DateTimeOffset.UtcNow.AddDays(14));
await _systemMessageService.CommitAsync(User.Identity.Name);
await _appHubSender.SystemMessageAddedAsync(walk.DogWalkerId);
await _pushNotificationService.SendWalkConfirmedAsync(walk.DogWalkerId, walk.Id);
var walkDto = Mapper.Map(walk);
return Ok(walkDto);
}
}
return NotFound(CommunicationErrors.Common_NotFound);
}
return BadRequest(CommunicationErrors.Common_Model_Invalid);
}
return NotFound(CommunicationErrors.Common_NotFound);
}
///
/// Zahlungsstatus eines Walks setzen
///
/// PublicWalkRequestCancelDto
/// HTTP 200 OK, Felher sonst
[HttpPost]
[Route("SetPaymentStatus")]
public async Task SetPaymentStatus(WalkPaymentStatusDto model)
{
var clientOffset = GetClientDateOffset();
if (User?.Identity != null && User.Identity.IsAuthenticated)
{
if (ModelState.IsValid)
{
var walk = await _walkService.GetAsync(model.WalkId);
if (walk != null)
{
walk.PaymentStatus = (PaymentStatus)model.PaymentStatus;
walk.UpdatedAt = model.UpdatedAt;
await _walkService.CommitAsync(User.Identity.Name);
return Ok();
}
return NotFound(CommunicationErrors.Common_NotFound);
}
return BadRequest(CommunicationErrors.Common_Model_Invalid);
}
return NotFound(CommunicationErrors.Common_NotFound);
}
///
/// Prüfen ob ein Walk gebucht werden kann
///
/// WalkPossibleDto
/// HTTP 200 OK, Felher sonst
[HttpPost]
[Route("IsWalkPossible")]
public async Task IsWalkPossible(WalkPossibleDto model)
{
var clientOffset = GetClientDateOffset();
if (User?.Identity != null && User.Identity.IsAuthenticated)
{
if (ModelState.IsValid)
{
var walkPossible = await _walkService.IsWalkPossibleAsync(model.DogWalkerId, model.Start, model.End);
return Ok(walkPossible);
}
return BadRequest(CommunicationErrors.Common_Model_Invalid);
}
return NotFound(CommunicationErrors.Common_NotFound);
}
///
/// Anlegen eines Walks wenn DIREKT! buchen möglich ist
///
/// WalkCreateDto
/// HTTP 200 OK, Felher sonst
[HttpPost]
[Route("CreateWalkDirect")]
public async Task CreateWalkDirect(WalkCreateDto model)
{
var clientOffset = GetClientDateOffset();
var result = new CreateResponseDto
{
Status = CreateStatusDto.Error,
Value = null
};
if (User?.Identity != null && User.Identity.IsAuthenticated)
{
if (ModelState.IsValid)
{
var appUserId = User.AppUserId();
var isLocked = await AppUserService.IsLockedAsync(appUserId);
var isBlocked = await AppUserService.IsBlockedAsync(model.DogWalkerId, appUserId);
var walkPossible = await _walkService.IsWalkPossibleAsync(model.DogWalkerId, model.Start, model.End);
if (walkPossible && !isLocked && !isBlocked)
{
//Nun einen Walk anlgegen!
var geometryFactory = NtsGeometryServices.Instance.CreateGeometryFactory(srid: 4326);
var geoLocationPickup = geometryFactory.CreatePoint(new Coordinate(model.PickupAddressLng, model.PickupAddressLat));
var geoLocationReturn = geometryFactory.CreatePoint(new Coordinate(model.ReturnAddressLng, model.ReturnAddressLat));
var walk = _walkService.Create();
walk.Type = (WalkType)model.Type;
walk.ServiceType = (WalkServiceType)model.ServiceType;
walk.DogWalkerId = model.DogWalkerId;
walk.DogOwnerId = model.DogOwnerId;
walk.PublicWalkRequestId = string.Empty;
walk.DogsJson = model.DogsJson;
walk.DogCount = model.DogCount;
walk.Start = model.Start;
walk.End = model.End;
walk.PickupAddress = Mapper.Map(model.PickupAddress);
walk.PickupLocation = geoLocationPickup;
walk.ReturnAddress = Mapper.Map(model.ReturnAddress);
walk.ReturnLocation = geoLocationReturn;
walk.Price = model.Price;
walk.Info = model.Info;
walk.Status = WalkStatus.Accepted;
walk.Started = null;
walk.Completed = null;
walk.Confirmed = null;
walk.Complained = null;
walk.ComplainReason = string.Empty;
walk.DeclinedReason = string.Empty;
walk.CancelledReason = string.Empty;
walk.CancelledBy = CancellationSource.None;
walk.CompletedInfo = string.Empty;
walk.Defactation = false;
walk.PaymentStatus = PaymentStatus.Pending;
walk.UpdatedAt = DateTimeOffset.UtcNow;
walk.Created = DateTimeOffset.UtcNow;
if (walk.Price == 0)
walk.PaymentStatus = PaymentStatus.Authorized;
_walkService.Add(walk);
await _walkService.CommitAsync(User.Identity.Name);
//Überlappende Walks die im Status "Request" sind, stornieren
if (walk.PaymentStatus is PaymentStatus.Authorized or PaymentStatus.Paid)
{
//Wenn der Preis eines Walks 0 ist, dann wird dieser direkt angelegt und gilt.
await _walkService.CancelWalkRequestsAsync(walk.DogWalkerId, walk.Start, walk.End);
await _walkService.CommitAsync(User.Identity.Name);
_systemMessageService.Add(walk.DogWalkerId, AppUserType.DogWalker, walk.Id, SystemMessageTables.Walk, SystemMessageType.WalkAdded, DateTimeOffset.UtcNow.AddDays(14));
await _systemMessageService.CommitAsync(User.Identity.Name);
await _appHubSender.SystemMessageAddedAsync(walk.DogWalkerId);
await _pushNotificationService.SendNewWalkAsync(walk.DogWalkerId, walk.Id);
}
result.Status = CreateStatusDto.Success;
result.Value = Mapper.Map(walk);
return Ok(result);
}
return NotFound(CommunicationErrors.Walk_NotPossible);
}
}
return BadRequest(CommunicationErrors.Common_Model_Invalid);
}
///
/// Anlegen eines Walks als Anfrage
///
/// WalkCreateDto
/// HTTP 200 OK, Felher sonst
[HttpPost]
[Route("CreateWalkRequest")]
public async Task CreateWalkRequest(WalkCreateDto model)
{
var clientOffset = GetClientDateOffset();
var result = new CreateResponseDto
{
Status = CreateStatusDto.Error,
Value = null
};
if (User?.Identity != null && User.Identity.IsAuthenticated)
{
if (ModelState.IsValid)
{
var appUserId = User.AppUserId();
var isLocked = await AppUserService.IsLockedAsync(appUserId);
var isBlocked = await AppUserService.IsBlockedAsync(model.DogWalkerId, appUserId);
var walkPossible = await _walkService.IsWalkPossibleAsync(model.DogWalkerId, model.Start, model.End);
if (walkPossible && !isLocked && !isBlocked)
{
//Nun einen Walk anlgegen!
var geometryFactory = NtsGeometryServices.Instance.CreateGeometryFactory(srid: 4326);
var geoLocationPickup = geometryFactory.CreatePoint(new Coordinate(model.PickupAddressLng, model.PickupAddressLat));
var geoLocationReturn = geometryFactory.CreatePoint(new Coordinate(model.ReturnAddressLng, model.ReturnAddressLat));
var walk = _walkService.Create();
walk.Type = (WalkType)model.Type;
walk.ServiceType = (WalkServiceType)model.ServiceType;
walk.DogWalkerId = model.DogWalkerId;
walk.DogOwnerId = model.DogOwnerId;
walk.PublicWalkRequestId = string.Empty;
walk.DogsJson = model.DogsJson;
walk.DogCount = model.DogCount;
walk.Start = model.Start;
walk.End = model.End;
walk.PickupAddress = Mapper.Map(model.PickupAddress);
walk.PickupLocation = geoLocationPickup;
walk.ReturnAddress = Mapper.Map(model.ReturnAddress);
walk.ReturnLocation = geoLocationReturn;
walk.Price = model.Price;
walk.Info = model.Info;
walk.Status = WalkStatus.Requested;
walk.Started = null;
walk.Completed = null;
walk.Confirmed = null;
walk.Complained = null;
walk.ComplainReason = string.Empty;
walk.DeclinedReason = string.Empty;
walk.CancelledReason = string.Empty;
walk.CancelledBy = CancellationSource.None;
walk.CompletedInfo = string.Empty;
walk.Defactation = false;
walk.PaymentStatus = PaymentStatus.None;
walk.UpdatedAt = DateTimeOffset.UtcNow;
walk.Created = DateTimeOffset.UtcNow;
_walkService.Add(walk);
await _walkService.CommitAsync(User.Identity.Name);
_systemMessageService.Add(walk.DogWalkerId, AppUserType.DogWalker, walk.Id, SystemMessageTables.Walk, SystemMessageType.WalkRequested, DateTimeOffset.UtcNow.AddDays(14));
await _systemMessageService.CommitAsync(User.Identity.Name);
await _appHubSender.SystemMessageAddedAsync(walk.DogWalkerId);
await _pushNotificationService.SendWalkRequestedAsync(walk.DogWalkerId, walk.Id);
result.Status = CreateStatusDto.Success;
result.Value = Mapper.Map(walk);
return Ok(result);
}
return NotFound(CommunicationErrors.Walk_NotPossible);
}
}
return BadRequest(CommunicationErrors.Common_Model_Invalid);
}
///
/// Akzeptieren eines Walks
///
/// WalkAcceptDto
/// HTTP 200 OK, Felher sonst
[HttpPost]
[Route("AcceptWalk")]
public async Task AcceptWalk(WalkAcceptDto model)
{
var clientOffset = GetClientDateOffset();
if (User?.Identity != null && User.Identity.IsAuthenticated)
{
if (ModelState.IsValid)
{
var walk = await _walkService.GetAsync(model.WalkId);
if (walk != null)
{
walk.Status = WalkStatus.Accepted;
walk.PaymentStatus = PaymentStatus.Pending;
walk.UpdatedAt = model.UpdatedAt;
if (walk.Price == 0)
walk.PaymentStatus = PaymentStatus.Authorized;
await _walkService.CommitAsync(User.Identity.Name);
_systemMessageService.Add(walk.DogOwnerId, AppUserType.DogOwner, walk.Id, SystemMessageTables.Walk, SystemMessageType.WalkAccepted, DateTimeOffset.UtcNow.AddDays(14));
await _systemMessageService.CommitAsync(User.Identity.Name);
await _appHubSender.SystemMessageAddedAsync(walk.DogOwnerId);
await _pushNotificationService.SendWalkAcceptedAsync(walk.DogOwnerId, walk.Id);
return Ok();
}
return NotFound(CommunicationErrors.Common_NotFound);
}
return BadRequest(CommunicationErrors.Common_Model_Invalid);
}
return NotFound(CommunicationErrors.Common_NotFound);
}
///
/// Ablehnen eines Walks
///
/// WalkDeclineDto
/// HTTP 200 OK, Felher sonst
[HttpPost]
[Route("DeclineWalk")]
public async Task DeclineWalk(WalkDeclineDto model)
{
var clientOffset = GetClientDateOffset();
if (User?.Identity != null && User.Identity.IsAuthenticated)
{
if (ModelState.IsValid)
{
var walk = await _walkService.GetAsync(model.WalkId);
if (walk != null)
{
walk.Status = WalkStatus.Declined;
walk.UpdatedAt = model.UpdatedAt;
walk.DeclinedReason = model.DeclineReason;
await _walkService.CommitAsync(User.Identity.Name);
_systemMessageService.Add(walk.DogOwnerId, AppUserType.DogOwner, walk.Id, SystemMessageTables.Walk, SystemMessageType.WalkDeclined, DateTimeOffset.UtcNow.AddDays(14));
await _systemMessageService.CommitAsync(User.Identity.Name);
await _appHubSender.SystemMessageAddedAsync(walk.DogOwnerId);
await _pushNotificationService.SendWalkDeclinedAsync(walk.DogOwnerId, walk.Id);
return Ok();
}
return NotFound(CommunicationErrors.Common_NotFound);
}
return BadRequest(CommunicationErrors.Common_Model_Invalid);
}
return NotFound(CommunicationErrors.Common_NotFound);
}
///
/// Erstellen einer Beschwerde zu einem Walk
///
/// WalkComplaintCreateDto
/// HTTP 200 OK, Felher sonst
[HttpPost]
[Route("CreateWalkComplaint")]
public async Task CreateWalkComplaint(WalkComplaintCreateDto model)
{
var clientOffset = GetClientDateOffset();
if (User?.Identity != null && User.Identity.IsAuthenticated)
{
if (ModelState.IsValid)
{
var walk = await _walkService.GetAsync(model.WalkId);
if (walk != null)
{
if (walk.Status == WalkStatus.Completed)
{
var complaint = _walkComplaintService.Create();
complaint.WalkId = walk.Id;
complaint.Source = WalkComplaintSource.DogOwner;
complaint.Type = (WalkComplaintType)model.Type;
complaint.Message = model.Message;
complaint.Status = WalkComplaintStatus.Open;
complaint.UserName = string.Empty;
complaint.Comment = string.Empty;
complaint.Resolved = null;
complaint.Created = DateTimeOffset.UtcNow;
_walkComplaintService.Add(complaint);
await _walkComplaintService.CommitAsync(User.Identity.Name);
walk.Status = WalkStatus.Complained;
walk.UpdatedAt = complaint.Created;
walk.Complained = complaint.Created;
walk.ComplainReason = model.Message;
await _walkService.CommitAsync(User.Identity.Name);
_systemMessageService.Add(walk.DogWalkerId, AppUserType.DogWalker, walk.Id, SystemMessageTables.Walk, SystemMessageType.WalkComplained, DateTimeOffset.UtcNow.AddDays(14));
await _systemMessageService.CommitAsync(User.Identity.Name);
await _appHubSender.SystemMessageAddedAsync(walk.DogWalkerId);
await _pushNotificationService.SendWalkComplainedAsync(walk.DogWalkerId, walk.Id);
//Jetzt Nachricht an den Support schicken
await _emailSender.SendEmailAsync(_walkComplaintOptions.Value.Email, _localizer["Email_WalkComplaint_Subject"] , _localizer["Email_WalkComplaint_Body"]);
var dto = Mapper.Map(walk);
return Ok(dto);
}
return BadRequest(CommunicationErrors.Walk_NotCompleted);
}
return NotFound(CommunicationErrors.Walk_NotFound);
}
return BadRequest(CommunicationErrors.Common_Model_Invalid);
}
return NotFound(CommunicationErrors.Common_NotFound);
}
///
/// Gibt eine Reklamation für einen Walk zurück
///
/// Id des Walks
/// Walk
[HttpGet]
[Route("GetWalkComplaint")]
public async Task GetWalkComplaint(string walkId)
{
var clientOffset = GetClientDateOffset();
if (User?.Identity != null && User.Identity.IsAuthenticated)
{
var walkComplaint = await _walkComplaintService.GetByWalkAsync(walkId);
if (walkComplaint != null)
{
var walkDto = Mapper.Map(walkComplaint);
return Ok(walkDto);
}
}
return NotFound(CommunicationErrors.Common_NotFound);
}
}
}