Florian Mihalits 38142f2435 Add payment type handling for walks
- Updated `Walk` class to include `PaymentType` property.
- Introduced `WalkPaymentTypeDto` enum for payment types.
- Modified DTOs (`PublicWalkRequestAcceptDto`, `WalkCreateDto`, `WalkDto`, `WalkWithNamesDto`) to include `PaymentType`.
- Enhanced `ApiWalksController` with new endpoints for accepting and canceling walks, and confirming walks with ratings.
- Updated `MappingProfile` for seamless conversion between `WalkPaymentType` and `WalkPaymentTypeDto`.
2025-06-30 15:08:57 +02:00

4041 lines
212 KiB
C#

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
{
/// <summary>
/// Controller für die Verwaltung von Walks
/// </summary>
[Authorize(AuthenticationSchemes = JwtBearerDefaults.AuthenticationScheme)]
[ApiController]
[ApiVersion(1)]
[ApiVersion(2)]
[Route("api/walks")]
[Route("api/v{v:apiVersion}/walks")]
public class ApiWalksController : ApiBaseController
{
private readonly ILogger<ApiWalksController> _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> _walkComplaintOptions;
private readonly IStringLocalizer<ApiWalksController> _localizer;
private readonly IPushNotificationService _pushNotificationService;
private readonly ICoinsService _coinsService;
private readonly IOptions<CoinsOptions> _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;
/// <summary>
/// Erstellt eine Instanz
/// </summary>
/// <param name="mapper">Instanz eines IMapper</param>
/// <param name="logger">Instanz eines ILogger</param>
/// <param name="localizationOptions">Instanz von LocalizationOptions</param>
/// <param name="appUserService">Instanz eines IDogOwnerService</param>
/// <param name="geoLocationService">Instanz eines IGeoLocationService</param>
/// <param name="publicWalkRequestService">Instanz eines IPublicWalkRequestService</param>
/// <param name="publicWalkResponseService">Instanz eines IPublicWalkResponseService</param>
/// <param name="walkService">Instanz eines IWalkService</param>
/// <param name="dogService">Instanz eines IDogService</param>
/// <param name="ratingService">Instanz eines IRatingService</param>
/// <param name="systemMessageService">Instanz eines ISystemMessageService</param>
/// <param name="appHubSender">Instanz eines IAppHubSender</param>
/// <param name="mangoPayService">Instanz eines IMangoPayService</param>
/// <param name="transactionFeeService">Instanz eines ITransactionFeeService</param>
/// <param name="walletService">Instanz eines IWalletService</param>
/// <param name="walkComplaintService">Instanz eines IWalkComplaintService</param>
/// <param name="emailSender">Instanz eines IEmailSender</param>
/// <param name="walkComplaintOptions">Einstellungen für Reklamationen</param>
/// <param name="localizer">Instanz eines IStringLocalizer</param>
/// <param name="pushNotificationService">Instanz eines IPushNotificationService</param>
/// <param name="coinsService">Instanz eines ICoinsService</param>
/// <param name="coinsOptions">Instanz von CoinsOptions</param>
/// <param name="voucherCampaignService">Instanz eines IVoucherCampaignService</param>
/// <param name="customerService">Instanz eines ICustomerService</param>
/// <param name="appUserReportService">Instanz eines IAppUserReportService</param>
/// <param name="userService">Instanz eines IUserService</param>
/// <param name="ticketStore">Instanz eines ITicketStore</param>
/// <param name="refreshTokenService">Instanz eines IRefreshTokenService</param>
public ApiWalksController(IMapper mapper, ILogger<ApiWalksController> logger, IOptions<LocalizationOptions> 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> walkComplaintOptions, IStringLocalizer<ApiWalksController> localizer, IPushNotificationService pushNotificationService,
ICoinsService coinsService, IOptions<CoinsOptions> 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;
}
/// <summary>
/// Abfrage der öffentlichen Anfragen eines AppUsers
/// </summary>
/// <param name="appUserId">Id des AppUsers</param>
/// <param name="lastUpdate">Letztes Update oder null, wenn noch keines</param>
/// <returns>Liste der Anfragen</returns>
[HttpGet]
[Route("GetPublicWalkRequestsForSync")]
public async Task<IActionResult> 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<List<PublicWalkRequestDto>>(requests);
return Ok(dtoList);
}
return NotFound(CommunicationErrors.Common_NotFound);
}
/// <summary>
/// Abfrage der öffentlichen Anfragen eines AppUsers "Latest"
/// </summary>
/// <param name="appUserId">Id des AppUsers</param>
/// <param name="language">Gewünschte Sprache</param>
/// <param name="take">Anahl gewünschte Anfragen</param>
/// <returns>Liste der Anfragen</returns>
[HttpGet]
[Route("GetPublicWalkRequestsLatest")]
public async Task<IActionResult> 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<DogMinInfo>();
if (!string.IsNullOrWhiteSpace(request.DogsJson))
{
var dogsList = JsonSerializer.Deserialize<List<DogWalkJson>>(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<List<PublicWalkRequestWithNamesDto>>(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);
}
/// <summary>
/// Abfrage der öffentlichen Anfragen
/// </summary>
/// <param name="model">Abfragemodel</param>
/// <returns>Liste der Anfragen</returns>
[HttpPost]
[Route("GetPublicWalkRequests")]
public async Task<IActionResult> GetPublicWalkRequests(PublicWalkRequestQueryDto model)
{
var clientOffset = GetClientDateOffset();
if (User?.Identity != null && User.Identity.IsAuthenticated)
{
var baseAddress = GetBaseAddress();
var response = new ListResponseDto<PublicWalkRequestWithNamesDto>();
//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<List<DynamicSortOrder>>(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<DogMinInfo>();
if (!string.IsNullOrWhiteSpace(request.DogsJson))
{
var dogsList = JsonSerializer.Deserialize<List<DogWalkJson>>(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<List<PublicWalkRequestWithNamesDto>>(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);
}
/// <summary>
/// Abfrage der öffentlichen Anfragen erweitert
/// </summary>
/// <param name="model">Abfragemodel</param>
/// <returns>Liste der Anfragen</returns>
[HttpPost]
[Route("GetPublicWalkRequestsEx")]
public async Task<IActionResult> GetPublicWalkRequestsEx(PublicWalkRequestQueryExDto model)
{
var clientOffset = GetClientDateOffset();
if (User?.Identity != null && User.Identity.IsAuthenticated)
{
var baseAddress = GetBaseAddress();
var response = new ListResponseDto<PublicWalkRequestWithNamesDto>();
//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<List<DynamicSortOrder>>(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<DogMinInfo>();
if (!string.IsNullOrWhiteSpace(request.DogsJson))
{
var dogsList = JsonSerializer.Deserialize<List<DogWalkJson>>(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<List<PublicWalkRequestWithNamesDto>>(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);
}
/// <summary>
/// Abfrage der öffentlichen Anfragen mit Antwort-Status für einen Dogwalker
/// </summary>
/// <param name="model">Abfragemodel</param>
/// <returns>Liste der Anfragen</returns>
[HttpPost]
[Route("GetPublicWalkRequestsAndResponseStatus")]
public async Task<IActionResult> GetPublicWalkRequestsAndResponseStatus(PublicWalkRequestAndResponseStatusQueryDto model)
{
var clientOffset = GetClientDateOffset();
if (User?.Identity != null && User.Identity.IsAuthenticated)
{
var baseAddress = GetBaseAddress();
var response = new ListResponseDto<PublicWalkRequestWithNamesAndResponseStatusDto>();
//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<List<DynamicSortOrder>>(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<DogMinInfo>();
if (!string.IsNullOrWhiteSpace(request.DogsJson))
{
var dogsList = JsonSerializer.Deserialize<List<DogWalkJson>>(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<List<PublicWalkRequestWithNamesAndResponseStatusDto>>(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);
}
/// <summary>
/// Abfrage der öffentlichen Anfragen mit Antwort-Status für einen Dogwalker - erweitert um suchparameter
/// </summary>
/// <param name="model">Abfragemodel</param>
/// <returns>Liste der Anfragen</returns>
[HttpPost]
[Route("GetPublicWalkRequestsAndResponseStatusEx")]
public async Task<IActionResult> GetPublicWalkRequestsAndResponseStatusEx(PublicWalkRequestAndResponseStatusQueryExDto model)
{
var clientOffset = GetClientDateOffset();
if (User?.Identity != null && User.Identity.IsAuthenticated)
{
var baseAddress = GetBaseAddress();
var response = new ListResponseDto<PublicWalkRequestWithNamesAndResponseStatusDto>();
//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<List<DynamicSortOrder>>(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<DogMinInfo>();
if (!string.IsNullOrWhiteSpace(request.DogsJson))
{
var dogsList = JsonSerializer.Deserialize<List<DogWalkJson>>(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<List<PublicWalkRequestWithNamesAndResponseStatusDto>>(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);
}
/// <summary>
/// Abfragen einer öffentlichen Anfrage
/// </summary>
/// <param name="id">Id der Anfrage</param>
/// <param name="language">Gewünschte Sprache</param>
/// <returns>Anfrage</returns>
[HttpGet]
[Route("GetPublicWalkRequests")]
public async Task<IActionResult> 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<DogMinInfo>();
if (!string.IsNullOrWhiteSpace(request.DogsJson))
{
var dogsList = JsonSerializer.Deserialize<List<DogWalkJson>>(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<PublicWalkRequestWithNamesDto>(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);
}
/// <summary>
/// Anlegen einer öffentlichen Anfrage
/// </summary>
/// <param name="model">CreateConversationDto</param>
/// <returns>HTTP 200 OK, Felher sonst</returns>
[HttpPost]
[Route("CreatePublicWalkRequest")]
public async Task<IActionResult> CreatePublicWalkRequest(PublicWalkRequestCreateDto model)
{
var clientOffset = GetClientDateOffset();
var result = new CreateResponseDto<PublicWalkRequestDto>
{
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<PublicWalkRequest>(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<PublicWalkRequestDto>(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<PublicWalkRequestDto>(publicWalkRequest);
}
else
{
result.Status = CreateStatusDto.Exists;
}
return Ok(result);
}
}
return BadRequest(CommunicationErrors.Common_Model_Invalid);
}
/// <summary>
/// Aktualisieren einer öffentlichen Anfrage
/// </summary>
/// <param name="model">PublicWalkRequestDto</param>
/// <returns>HTTP 200 OK, Felher sonst</returns>
[HttpPost]
[Route("UpdatePublicWalkRequest")]
public async Task<IActionResult> 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);
}
/// <summary>
/// Löschen einer öffentlichen Anfrage
/// </summary>
/// <param name="model">PublicWalkRequestDto</param>
/// <param name="appUserId">Id des App-Users</param>
/// <returns>200OK</returns>
[HttpPost]
[Route("DeletePublicWalkRequest")]
public async Task<IActionResult> 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);
}
/// <summary>
/// Akzeptieren einer Antwort zu einer öffentlichen Anfrage
/// </summary>
/// <param name="model">PublicWalkRequestDto</param>
/// <returns>HTTP 200 OK, Felher sonst</returns>
[HttpPost]
[Route("AcceptPublicWalkRequest")]
public async Task<IActionResult> 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<WalkDto>(walk);
return Ok(walkDto);
}
}
return NotFound(CommunicationErrors.Common_NotFound);
}
return BadRequest(CommunicationErrors.Common_Model_Invalid);
}
return NotFound(CommunicationErrors.Common_NotFound);
}
/// <summary>
/// Akzeptieren einer Antwort zu einer öffentlichen Anfrage
/// </summary>
/// <param name="model">PublicWalkRequestDto</param>
/// <returns>HTTP 200 OK, Felher sonst</returns>
[HttpPost]
[Route("AcceptPublicWalkRequest")]
[MapToApiVersion(2)]
public async Task<IActionResult> AcceptPublicWalkRequestV2(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.PaymentType = (WalkPaymentType)model.PaymentType;
walk.UpdatedAt = DateTimeOffset.UtcNow;
walk.Created = DateTimeOffset.UtcNow;
if (walk.Price == 0 || walk.PaymentType == WalkPaymentType.Cash)
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<WalkDto>(walk);
return Ok(walkDto);
}
}
return NotFound(CommunicationErrors.Common_NotFound);
}
return BadRequest(CommunicationErrors.Common_Model_Invalid);
}
return NotFound(CommunicationErrors.Common_NotFound);
}
/// <summary>
/// Stornieren einer öffentlichen Anfrage
/// </summary>
/// <param name="model">PublicWalkRequestCancelDto</param>
/// <returns>HTTP 200 OK, Felher sonst</returns>
[HttpPost]
[Route("CancelPublicWalkRequest")]
public async Task<IActionResult> 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);
}
/// <summary>
/// Anzahl der öffentlichen Anfragen eines AppUsers
/// </summary>
/// <returns>Anzahl öffentliche Anfragen</returns>
[HttpGet]
[Route("CountPublicWalkRequests")]
public async Task<IActionResult> 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);
}
/// <summary>
/// Abfrage der Antworten auf öffentlichen Anfragen eines AppUsers
/// </summary>
/// <param name="appUserId">Id des AppUsers</param>
/// <param name="lastUpdate">Letztes Update oder null, wenn noch keines</param>
/// <returns>Liste der Anfragen</returns>
[HttpGet]
[Route("GetPublicWalkResponsesForSync")]
public async Task<IActionResult> 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<List<PublicWalkResponseDto>>(requests);
return Ok(dtoList);
}
return NotFound(CommunicationErrors.Common_NotFound);
}
/// <summary>
/// Abfrage einer Antwort auf öffentlichen Anfragen
/// </summary>
/// <param name="publicWalkResponseId">Id der Antwort zur öffentlichen Anfrage</param>
/// <returns>Liste der Anfragen</returns>
[HttpGet]
[Route("GetPublicWalkResponse")]
public async Task<IActionResult> 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<PublicWalkResponseDto>(response);
return Ok(dto);
}
}
return NotFound(CommunicationErrors.Common_NotFound);
}
/// <summary>
/// Abfrage einer Antwort auf öffentlichen Anfragen mit Namen aufgelöst
/// </summary>
/// <param name="publicWalkResponseId">Id der Antwort zur öffentlichen Anfrage</param>
/// <returns>Liste der Anfragen</returns>
[HttpGet]
[Route("GetPublicWalkResponseWithNames")]
public async Task<IActionResult> 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<PublicWalkResponseWithNamesDto>(response);
var baseAddress = GetBaseAddress();
dto.DogWalkerPhoto = $"{baseAddress}/file/documents/thumbnails/{400}/{dto.DogWalkerPhoto}";
return Ok(dto);
}
}
return NotFound(CommunicationErrors.Common_NotFound);
}
/// <summary>
/// Abfrage einer Antwort auf öffentlichen Anfragen eines Walkers
/// </summary>
/// <param name="publicWalkRequestId">Id der öffentlichen Anfrage</param>
/// <param name="appUserId">Id des AppUsers</param>
/// <returns>Liste der Anfragen</returns>
[HttpGet]
[Route("GetPublicWalkResponseForWalker")]
public async Task<IActionResult> 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<PublicWalkResponseDto>(response);
return Ok(dto);
}
}
return NotFound(CommunicationErrors.Common_NotFound);
}
/// <summary>
/// Anlegen einer Antwort zu einer öffentlichen Anfrage
/// </summary>
/// <param name="model">PublicWalkResponseDto</param>
/// <returns>HTTP 200 OK, Felher sonst</returns>
[HttpPost]
[Route("CreatePublicWalkResponse")]
public async Task<IActionResult> CreatePublicWalkResponse(PublicWalkResponseDto model)
{
var clientOffset = GetClientDateOffset();
var result = new CreateResponseDto<PublicWalkResponseDto>
{
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<PublicWalkResponse>(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<PublicWalkResponseDto>(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);
}
/// <summary>
/// Aktualisieren einer Antwort zu einer öffentlichen Anfrage
/// </summary>
/// <param name="model">PublicWalkRequestDto</param>
/// <returns>HTTP 200 OK, Felher sonst</returns>
[HttpPost]
[Route("UpdatePublicWalkResponse")]
public async Task<IActionResult> 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);
}
/// <summary>
/// Löschen einer Antwort zu einer öffentlichen Anfrage
/// </summary>
/// <param name="model">PublicWalkRequestDto</param>
/// <param name="appUserId">Id des App-Users</param>
/// <returns>200OK</returns>
[HttpPost]
[Route("DeletePublicWalkResponse")]
public async Task<IActionResult> 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);
}
/// <summary>
/// Abfrage der Antworten zu einer öffentlichen Anfragen
/// </summary>
/// <param name="model">Abfragemodel</param>
/// <returns>Liste der Anfragen</returns>
[HttpPost]
[Route("GetPublicWalkResponses")]
public async Task<IActionResult> GetPublicWalkResponses(PublicWalkResponseQueryDto model)
{
var clientOffset = GetClientDateOffset();
if (User?.Identity != null && User.Identity.IsAuthenticated)
{
var response = new ListResponseDto<PublicWalkResponseWithNamesDto>();
//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<List<PublicWalkResponseWithNamesDto>>(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);
}
/// <summary>
/// Ablehenen eines Angebotes für eine öffentliche Anfrage
/// </summary>
/// <param name="model"></param>
/// <returns></returns>
[HttpPost]
[Route("DeclinePublicWalkResponse")]
public async Task<IActionResult> 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);
}
/// <summary>
/// Bearbeiten eines Bereits gestellten Angebotes für eine öffentliche Anfrage
/// </summary>
/// <param name="model">PublicWalkResponseEditDto</param>
/// <returns>200OK</returns>
[HttpPost]
[Route("EditPublicWalkResponse")]
public async Task<IActionResult> 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);
}
/// <summary>
/// Stornieren eines bereits gestellten Angebotes für eine öffentliche Anfrage
/// </summary>
/// <param name="model">PublicWalkResponseEditDto</param>
/// <returns>200OK</returns>
[HttpPost]
[Route("CancelPublicWalkResponse")]
public async Task<IActionResult> 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);
}
/// <summary>
/// Abfrage der Walks eines AppUsers
/// </summary>
/// <param name="appUserId">Id des AppUsers</param>
/// <param name="lastUpdate">Letztes Update oder null, wenn noch keines</param>
/// <returns>Liste der Anfragen</returns>
[HttpGet]
[Route("GetWalksForSync")]
public async Task<IActionResult> 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<List<WalkDto>>(requests);
return Ok(dtoList);
}
return NotFound(CommunicationErrors.Common_NotFound);
}
/// <summary>
/// Anlegen eines Walks
/// </summary>
/// <param name="model">WalkDto</param>
/// <returns>HTTP 200 OK, Felher sonst</returns>
[HttpPost]
[Route("CreateWalk")]
public async Task<IActionResult> CreateWalk(WalkDto model)
{
var clientOffset = GetClientDateOffset();
var result = new CreateResponseDto<WalkDto>
{
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<Walk>(model);
_walkService.Add(walk);
await _walkService.CommitAsync(User.Identity.Name);
result.Status = CreateStatusDto.Success;
result.Value = Mapper.Map<WalkDto>(walk);
}
else
{
result.Status = CreateStatusDto.Exists;
}
return Ok(result);
}
}
return BadRequest(CommunicationErrors.Common_Model_Invalid);
}
/// <summary>
/// Aktualisieren eines Walks
/// </summary>
/// <param name="model">WalkDto</param>
/// <returns>HTTP 200 OK, Felher sonst</returns>
[HttpPost]
[Route("UpdateWalk")]
public async Task<IActionResult> 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);
}
/// <summary>
/// Löschen eines Walks
/// </summary>
/// <param name="model">WalkDto</param>
/// <param name="appUserId">Id des App-Users</param>
/// <returns>200OK</returns>
[HttpPost]
[Route("DeleteWalk")]
public async Task<IActionResult> 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);
}
/// <summary>
/// Abfragen von Walks - wird eigentlich nur von Hundebesitzern aufgerufen
/// </summary>
/// <param name="model">Abfragemodel</param>
/// <returns>Liste von Walks</returns>
[HttpPost]
[Route("GetWalks")]
public async Task<IActionResult> GetWalks(WalksQueryDto model)
{
var clientOffset = GetClientDateOffset();
if (User?.Identity != null && User.Identity.IsAuthenticated)
{
var baseAddress = GetBaseAddress();
var response = new ListResponseDto<WalkWithNamesDto>();
//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<List<DynamicSortOrder>>(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<DogMinInfo>();
if (!string.IsNullOrWhiteSpace(walk.DogsJson))
{
var dogsList = JsonSerializer.Deserialize<List<DogWalkJson>>(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<List<WalkWithNamesDto>>(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);
}
/// <summary>
/// Abfragen von Walks für einen Walker.
/// Sondersituation: Walker bekommen keine Walks mit einem PaymentStatus unter Authorized zurück
/// </summary>
/// <param name="model">Abfragemodel</param>
/// <returns>Liste von Walks</returns>
[HttpPost]
[Route("GetWalksWalker")]
public async Task<IActionResult> GetWalksWalker(WalksQueryDto model)
{
var clientOffset = GetClientDateOffset();
if (User?.Identity != null && User.Identity.IsAuthenticated)
{
var baseAddress = GetBaseAddress();
var response = new ListResponseDto<WalkWithNamesDto>();
//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<List<DynamicSortOrder>>(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<DogMinInfo>();
if (!string.IsNullOrWhiteSpace(walk.DogsJson))
{
var dogsList = JsonSerializer.Deserialize<List<DogWalkJson>>(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<List<WalkWithNamesDto>>(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);
}
/// <summary>
/// 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
/// </summary>
/// <param name="model">WalksNextQueryDto</param>
/// <returns>Liste von Walks</returns>
[HttpPost]
[Route("GetNextWalksOwner")]
public async Task<IActionResult> GetNextWalksOwner(WalksNextQueryDto model)
{
var clientOffset = GetClientDateOffset();
if (User?.Identity != null && User.Identity.IsAuthenticated)
{
var baseAddress = GetBaseAddress();
var response = new ListResponseDto<WalkWithNamesDto>();
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<DogMinInfo>();
if (!string.IsNullOrWhiteSpace(walk.DogsJson))
{
var dogsList = JsonSerializer.Deserialize<List<DogWalkJson>>(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<List<WalkWithNamesDto>>(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);
}
/// <summary>
/// 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
/// </summary>
/// <param name="model">WalksNextQueryDto</param>
/// <returns>Liste von Walks</returns>
[HttpPost]
[Route("GetNextWalksWalker")]
public async Task<IActionResult> GetNextWalksWalker(WalksNextQueryDto model)
{
var clientOffset = GetClientDateOffset();
if (User?.Identity != null && User.Identity.IsAuthenticated)
{
var baseAddress = GetBaseAddress();
var response = new ListResponseDto<WalkWithNamesDto>();
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<DogMinInfo>();
if (!string.IsNullOrWhiteSpace(walk.DogsJson))
{
var dogsList = JsonSerializer.Deserialize<List<DogWalkJson>>(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<List<WalkWithNamesDto>>(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);
}
/// <summary>
/// Gibt einen Walk mit Namen zurück
/// </summary>
/// <param name="walkId">Id des Walks</param>
/// <param name="language">Gewünschte Sprache</param>
/// <returns>Walk</returns>
[HttpGet]
[Route("GetWalkWithNames")]
public async Task<IActionResult> 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<WalkWithNamesDto>(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<DogMinInfoDto>();
if (!string.IsNullOrWhiteSpace(walk.DogsJson))
{
var dogsList = JsonSerializer.Deserialize<List<DogWalkJson>>(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);
}
/// <summary>
/// Gibt einen Walk zurück der mit einer öffentlichen Anfrage verknüpft ist
/// </summary>
/// <param name="publicWalkRequestId">Id der öffentlichen Anfrage</param>
/// <returns>Walk</returns>
[HttpGet]
[Route("GetWalkByPublicRequest")]
public async Task<IActionResult> 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<WalkDto>(walk);
return Ok(walkDto);
}
}
return NotFound(CommunicationErrors.Common_NotFound);
}
/// <summary>
/// Stornieren eines Walks
/// </summary>
/// <param name="model">PublicWalkRequestCancelDto</param>
/// <returns>HTTP 200 OK, Fehler sonst</returns>
[HttpPost]
[Route("CancelWalk")]
public async Task<IActionResult> 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);
}
/// <summary>
/// Stornieren eines Walks
/// </summary>
/// <param name="model">PublicWalkRequestCancelDto</param>
/// <returns>HTTP 200 OK, Fehler sonst</returns>
[HttpPost]
[Route("CancelWalk")]
[MapToApiVersion(2)]
public async Task<IActionResult> CancelWalkV2(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 && walk.PaymentType == WalkPaymentType.MangoPay)
{
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 && walk.PaymentType == WalkPaymentType.MangoPay)
{
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
if (walk.PaymentType == WalkPaymentType.MangoPay)
{
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);
}
/// <summary>
/// Starten eines Walks
/// </summary>
/// <param name="model">PublicWalkRequestCancelDto</param>
/// <returns>HTTP 200 OK, Felher sonst</returns>
[HttpPost]
[Route("StartWalk")]
public async Task<IActionResult> 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);
}
/// <summary>
/// abschließen eines Walks - Alte Version mit Bewertung von Walk.
/// Wird durch CompleteWalkEx ersetzt, welches die Bewertung des Hundebesitzers implementiert
/// </summary>
/// <param name="model">WalkCompleteDto</param>
/// <returns>HTTP 200 OK, Felher sonst</returns>
[HttpPost]
[Route("CompleteWalk")]
public async Task<IActionResult> 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<List<DogWalkJson>>(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<List<DogWalkJson>>(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);
}
/// <summary>
/// Abschließen eines Walks - mit Bewertung Hundebesitzer anstatt des Walks
/// </summary>
/// <param name="model">WalkCompleteDto</param>
/// <returns>HTTP 200 OK, Felher sonst</returns>
[HttpPost]
[Route("CompleteWalkEx")]
public async Task<IActionResult> 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<List<DogWalkJson>>(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<List<DogWalkJson>>(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);
}
/// <summary>
/// Bestätigen eines Walks
/// </summary>
/// <param name="model">WalkConfirmDto</param>
/// <returns>HTTP 200 OK, Felher sonst</returns>
[HttpPost]
[Route("ConfirmWalk")]
public async Task<IActionResult> 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<WalkDto>(walk);
return Ok(walkDto);
}
}
return NotFound(CommunicationErrors.Common_NotFound);
}
return BadRequest(CommunicationErrors.Common_Model_Invalid);
}
return NotFound(CommunicationErrors.Common_NotFound);
}
/// <summary>
/// Bestätigen eines Walks
/// </summary>
/// <param name="model">WalkConfirmDto</param>
/// <returns>HTTP 200 OK, Felher sonst</returns>
[HttpPost]
[Route("ConfirmWalk")]
[MapToApiVersion(2)]
public async Task<IActionResult> ConfirmWalkV2(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");
}
}
}
if (walk.PaymentType == WalkPaymentType.MangoPay)
{
//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<WalkDto>(walk);
return Ok(walkDto);
}
}
return NotFound(CommunicationErrors.Common_NotFound);
}
return BadRequest(CommunicationErrors.Common_Model_Invalid);
}
return NotFound(CommunicationErrors.Common_NotFound);
}
/// <summary>
/// Bestätigen eines Walks mit Rating
/// </summary>
/// <param name="model">WalkConfirmDto</param>
/// <returns>HTTP 200 OK, Felher sonst</returns>
[HttpPost]
[Route("ConfirmWalkWithRating")]
public async Task<IActionResult> 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<WalkDto>(walk);
return Ok(walkDto);
}
}
return NotFound(CommunicationErrors.Common_NotFound);
}
return BadRequest(CommunicationErrors.Common_Model_Invalid);
}
return NotFound(CommunicationErrors.Common_NotFound);
}
/// <summary>
/// Bestätigen eines Walks mit Rating
/// </summary>
/// <param name="model">WalkConfirmDto</param>
/// <returns>HTTP 200 OK, Felher sonst</returns>
[HttpPost]
[Route("ConfirmWalkWithRating")]
[MapToApiVersion(2)]
public async Task<IActionResult> ConfirmWalkWithRatingV2(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");
}
}
}
if (walk.PaymentType == WalkPaymentType.MangoPay)
{
//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<WalkDto>(walk);
return Ok(walkDto);
}
}
return NotFound(CommunicationErrors.Common_NotFound);
}
return BadRequest(CommunicationErrors.Common_Model_Invalid);
}
return NotFound(CommunicationErrors.Common_NotFound);
}
/// <summary>
/// Zahlungsstatus eines Walks setzen
/// </summary>
/// <param name="model">PublicWalkRequestCancelDto</param>
/// <returns>HTTP 200 OK, Felher sonst</returns>
[HttpPost]
[Route("SetPaymentStatus")]
public async Task<IActionResult> 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);
}
/// <summary>
/// Prüfen ob ein Walk gebucht werden kann
/// </summary>
/// <param name="model">WalkPossibleDto</param>
/// <returns>HTTP 200 OK, Felher sonst</returns>
[HttpPost]
[Route("IsWalkPossible")]
public async Task<IActionResult> 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);
}
/// <summary>
/// Anlegen eines Walks wenn DIREKT! buchen möglich ist
/// </summary>
/// <param name="model">WalkCreateDto</param>
/// <returns>HTTP 200 OK, Felher sonst</returns>
[HttpPost]
[Route("CreateWalkDirect")]
public async Task<IActionResult> CreateWalkDirect(WalkCreateDto model)
{
var clientOffset = GetClientDateOffset();
var result = new CreateResponseDto<WalkDto>
{
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<Address>(model.PickupAddress);
walk.PickupLocation = geoLocationPickup;
walk.ReturnAddress = Mapper.Map<Address>(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<WalkDto>(walk);
return Ok(result);
}
return NotFound(CommunicationErrors.Walk_NotPossible);
}
}
return BadRequest(CommunicationErrors.Common_Model_Invalid);
}
/// <summary>
/// Anlegen eines Walks wenn DIREKT! buchen möglich ist
/// </summary>
/// <param name="model">WalkCreateDto</param>
/// <returns>HTTP 200 OK, Felher sonst</returns>
[HttpPost]
[Route("CreateWalkDirect")]
[MapToApiVersion(2)]
public async Task<IActionResult> CreateWalkDirectV2(WalkCreateDto model)
{
var clientOffset = GetClientDateOffset();
var result = new CreateResponseDto<WalkDto>
{
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<Address>(model.PickupAddress);
walk.PickupLocation = geoLocationPickup;
walk.ReturnAddress = Mapper.Map<Address>(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.PaymentType = (WalkPaymentType)model.PaymentType;
walk.UpdatedAt = DateTimeOffset.UtcNow;
walk.Created = DateTimeOffset.UtcNow;
if (walk.Price == 0 || walk.PaymentType == WalkPaymentType.Cash)
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<WalkDto>(walk);
return Ok(result);
}
return NotFound(CommunicationErrors.Walk_NotPossible);
}
}
return BadRequest(CommunicationErrors.Common_Model_Invalid);
}
/// <summary>
/// Anlegen eines Walks als Anfrage
/// </summary>
/// <param name="model">WalkCreateDto</param>
/// <returns>HTTP 200 OK, Felher sonst</returns>
[HttpPost]
[Route("CreateWalkRequest")]
public async Task<IActionResult> CreateWalkRequest(WalkCreateDto model)
{
var clientOffset = GetClientDateOffset();
var result = new CreateResponseDto<WalkDto>
{
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<Address>(model.PickupAddress);
walk.PickupLocation = geoLocationPickup;
walk.ReturnAddress = Mapper.Map<Address>(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<WalkDto>(walk);
return Ok(result);
}
return NotFound(CommunicationErrors.Walk_NotPossible);
}
}
return BadRequest(CommunicationErrors.Common_Model_Invalid);
}
/// <summary>
/// Anlegen eines Walks als Anfrage
/// </summary>
/// <param name="model">WalkCreateDto</param>
/// <returns>HTTP 200 OK, Felher sonst</returns>
[HttpPost]
[Route("CreateWalkRequest")]
[MapToApiVersion(2)]
public async Task<IActionResult> CreateWalkRequestV2(WalkCreateDto model)
{
var clientOffset = GetClientDateOffset();
var result = new CreateResponseDto<WalkDto>
{
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<Address>(model.PickupAddress);
walk.PickupLocation = geoLocationPickup;
walk.ReturnAddress = Mapper.Map<Address>(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.PaymentType = (WalkPaymentType)model.PaymentType;
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<WalkDto>(walk);
return Ok(result);
}
return NotFound(CommunicationErrors.Walk_NotPossible);
}
}
return BadRequest(CommunicationErrors.Common_Model_Invalid);
}
/// <summary>
/// Akzeptieren eines Walks
/// </summary>
/// <param name="model">WalkAcceptDto</param>
/// <returns>HTTP 200 OK, Felher sonst</returns>
[HttpPost]
[Route("AcceptWalk")]
public async Task<IActionResult> 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);
}
/// <summary>
/// Akzeptieren eines Walks
/// </summary>
/// <param name="model">WalkAcceptDto</param>
/// <returns>HTTP 200 OK, Felher sonst</returns>
[HttpPost]
[Route("AcceptWalk")]
[MapToApiVersion(2)]
public async Task<IActionResult> AcceptWalkV2(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.PaymentType == WalkPaymentType.Cash)
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);
}
/// <summary>
/// Ablehnen eines Walks
/// </summary>
/// <param name="model">WalkDeclineDto</param>
/// <returns>HTTP 200 OK, Felher sonst</returns>
[HttpPost]
[Route("DeclineWalk")]
public async Task<IActionResult> 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);
}
/// <summary>
/// Erstellen einer Beschwerde zu einem Walk
/// </summary>
/// <param name="model">WalkComplaintCreateDto</param>
/// <returns>HTTP 200 OK, Felher sonst</returns>
[HttpPost]
[Route("CreateWalkComplaint")]
public async Task<IActionResult> 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<WalkDto>(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);
}
/// <summary>
/// Gibt eine Reklamation für einen Walk zurück
/// </summary>
/// <param name="walkId">Id des Walks</param>
/// <returns>Walk</returns>
[HttpGet]
[Route("GetWalkComplaint")]
public async Task<IActionResult> 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<WalkComplaintDto>(walkComplaint);
return Ok(walkDto);
}
}
return NotFound(CommunicationErrors.Common_NotFound);
}
}
}