Compare commits
5 Commits
ecb43012ac
...
fafbc55732
| Author | SHA1 | Date | |
|---|---|---|---|
| fafbc55732 | |||
| 555273aed1 | |||
| b481a3999a | |||
| 38142f2435 | |||
| ada8b7a200 |
@ -3933,4 +3933,13 @@
|
||||
<data name="Subscription_MaxRegisteredDate" xml:space="preserve">
|
||||
<value>Max. Registrierungsdatum</value>
|
||||
</data>
|
||||
<data name="WalkPaymentType_MangoPay" xml:space="preserve">
|
||||
<value>Mangopay</value>
|
||||
</data>
|
||||
<data name="WalkPaymentType_Cash" xml:space="preserve">
|
||||
<value>Barzahlung</value>
|
||||
</data>
|
||||
<data name="Walk_PaymentType" xml:space="preserve">
|
||||
<value>Zahlungsart</value>
|
||||
</data>
|
||||
</root>
|
||||
@ -3935,4 +3935,13 @@
|
||||
<data name="Subscription_MaxRegisteredDate" xml:space="preserve">
|
||||
<value>Max. registered date</value>
|
||||
</data>
|
||||
<data name="WalkPaymentType_MangoPay" xml:space="preserve">
|
||||
<value>Mangopay</value>
|
||||
</data>
|
||||
<data name="WalkPaymentType_Cash" xml:space="preserve">
|
||||
<value>Cash</value>
|
||||
</data>
|
||||
<data name="Walk_PaymentType" xml:space="preserve">
|
||||
<value>Payment tye</value>
|
||||
</data>
|
||||
</root>
|
||||
@ -3934,4 +3934,13 @@
|
||||
<data name="Subscription_MaxRegisteredDate" xml:space="preserve">
|
||||
<value />
|
||||
</data>
|
||||
<data name="WalkPaymentType_MangoPay" xml:space="preserve">
|
||||
<value />
|
||||
</data>
|
||||
<data name="WalkPaymentType_Cash" xml:space="preserve">
|
||||
<value />
|
||||
</data>
|
||||
<data name="Walk_PaymentType" xml:space="preserve">
|
||||
<value />
|
||||
</data>
|
||||
</root>
|
||||
@ -50,6 +50,7 @@ namespace gehGassi.Core.Services
|
||||
var walk = new Walk()
|
||||
{
|
||||
Id = Guid.NewGuid().ToString("N"),
|
||||
PaymentType = WalkPaymentType.MangoPay,
|
||||
Created = DateTimeOffset.UtcNow
|
||||
};
|
||||
return walk;
|
||||
@ -591,6 +592,8 @@ namespace gehGassi.Core.Services
|
||||
walk.PaymentStatus = PaymentStatus.Paid;
|
||||
await CommitAsync("System");
|
||||
|
||||
if (walk.PaymentType == WalkPaymentType.MangoPay)
|
||||
{
|
||||
decimal feeDecimal = 0;
|
||||
long feeFromUser = 0;
|
||||
long feeFromVoucher = 0;
|
||||
@ -669,6 +672,7 @@ namespace gehGassi.Core.Services
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return walks.Count();
|
||||
}
|
||||
|
||||
@ -303,6 +303,21 @@ namespace gehGassi.Domain.Common
|
||||
PayPal = 30
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Zahlungsart für einen Walk
|
||||
/// </summary>
|
||||
public enum WalkPaymentType
|
||||
{
|
||||
/// <summary>
|
||||
/// Mit MangoPay bezahlen (z.B. Kreditkarte)
|
||||
/// </summary>
|
||||
MangoPay = 1,
|
||||
/// <summary>
|
||||
/// Barzahlung
|
||||
/// </summary>
|
||||
Cash = 10
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Zahlungsstatus
|
||||
/// </summary>
|
||||
|
||||
@ -178,6 +178,12 @@ namespace gehGassi.Domain.Walks
|
||||
[Required]
|
||||
public PaymentStatus PaymentStatus { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// Welche Art von Bezahlung wurde verwendet
|
||||
/// </summary>
|
||||
[Required]
|
||||
public WalkPaymentType PaymentType { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// Id des Gutscheins der verwendet wurde, wenn einer verwendet wurde
|
||||
/// </summary>
|
||||
@ -473,6 +479,11 @@ namespace gehGassi.Domain.Walks
|
||||
/// </summary>
|
||||
public PaymentStatus PaymentStatus { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// Welche Art von Bezahlung wurde verwendet
|
||||
/// </summary>
|
||||
public WalkPaymentType PaymentType { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// Id des Gutscheins der verwendet wurde, wenn einer verwendet wurde
|
||||
/// </summary>
|
||||
|
||||
@ -584,6 +584,21 @@ namespace gehGassi.Dto.Common
|
||||
RefundendAndPayed = 60
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Zahlungsart für einen Walk
|
||||
/// </summary>
|
||||
public enum WalkPaymentTypeDto
|
||||
{
|
||||
/// <summary>
|
||||
/// Mit MangoPay bezahlen (z.B. Kreditkarte)
|
||||
/// </summary>
|
||||
MangoPay = 1,
|
||||
/// <summary>
|
||||
/// Barzahlung
|
||||
/// </summary>
|
||||
Cash = 10
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Sortierreihenfolge
|
||||
/// </summary>
|
||||
|
||||
@ -2,6 +2,7 @@
|
||||
using System.Collections.Generic;
|
||||
using System.ComponentModel.DataAnnotations;
|
||||
using System.Text;
|
||||
using gehGassi.Dto.Common;
|
||||
|
||||
namespace gehGassi.Dto.Walks
|
||||
{
|
||||
@ -36,5 +37,9 @@ namespace gehGassi.Dto.Walks
|
||||
/// </summary>
|
||||
public DateTimeOffset UpdatedAt { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// Zahlungsart für den Walk
|
||||
/// </summary>
|
||||
public WalkPaymentTypeDto? PaymentType { get; set; }
|
||||
}
|
||||
}
|
||||
|
||||
@ -101,5 +101,10 @@ namespace gehGassi.Dto.Walks
|
||||
/// </summary>
|
||||
[MaxLength(500)]
|
||||
public string Info { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// Zahlungsart für den Walk
|
||||
/// </summary>
|
||||
public WalkPaymentTypeDto? PaymentType { get; set; }
|
||||
}
|
||||
}
|
||||
|
||||
@ -179,6 +179,11 @@ namespace gehGassi.Dto.Walks
|
||||
[Required]
|
||||
public PaymentStatusDto PaymentStatus { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// Zahlungsart für den Walk
|
||||
/// </summary>
|
||||
public WalkPaymentTypeDto PaymentType { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// Datum der Erstellung des Walks
|
||||
/// </summary>
|
||||
|
||||
@ -204,6 +204,11 @@ namespace gehGassi.Dto.Walks
|
||||
/// </summary>
|
||||
public PaymentStatusDto PaymentStatus { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// Zahlungsart für den Walk
|
||||
/// </summary>
|
||||
public WalkPaymentTypeDto PaymentType { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// Id des Gutscheins der verwendet wurde, wenn einer verwendet wurde
|
||||
/// </summary>
|
||||
|
||||
9478
gehGassi.Persistence/Migrations/20250630082853_Walk_PaymentType_Added.Designer.cs
generated
Normal file
9478
gehGassi.Persistence/Migrations/20250630082853_Walk_PaymentType_Added.Designer.cs
generated
Normal file
File diff suppressed because it is too large
Load Diff
@ -0,0 +1,65 @@
|
||||
using Microsoft.EntityFrameworkCore.Migrations;
|
||||
using System;
|
||||
|
||||
#nullable disable
|
||||
|
||||
namespace gehGassi.Persistence.Migrations
|
||||
{
|
||||
/// <inheritdoc />
|
||||
public partial class Walk_PaymentType_Added : Migration
|
||||
{
|
||||
/// <inheritdoc />
|
||||
protected override void Up(MigrationBuilder migrationBuilder)
|
||||
{
|
||||
migrationBuilder.AddColumn<int>(
|
||||
name: "PaymentType",
|
||||
table: "Walks",
|
||||
type: "int",
|
||||
nullable: false,
|
||||
defaultValue: 0);
|
||||
|
||||
migrationBuilder.Sql("Update Walks SET PaymentType = 1");
|
||||
|
||||
|
||||
var viewName = "tv_WalksWithNames";
|
||||
var sql = @"CREATE FUNCTION tv_WalksWithNames() RETURNS TABLE AS RETURN
|
||||
SELECT W.*,
|
||||
CONCAT(DW.FirstName, ' ' , DW.LastName) AS DogWalkerName, DW.Photo AS DogWalkerPhoto,
|
||||
IsNull(DW.Locked,0) AS DogWalkerLocked, CAST((SELECT CASE WHEN AUBDW.Id IS NOT NULL THEN 1 ELSE 0 END) AS BIT) AS DogWalkerBlocked,
|
||||
CONCAT(DO.FirstName, ' ' , DO.LastName) AS DogOwnerName, DO.Photo AS DogOwnerPhoto,
|
||||
IsNull(DO.Locked,0) AS DogOwnerLocked, CAST((SELECT CASE WHEN AUBDO.Id IS NOT NULL THEN 1 ELSE 0 END) AS BIT) AS DogOwnerBlocked
|
||||
FROM Walks W
|
||||
LEFT JOIN AppUsers DW ON W.DogWalkerId = DW.Id
|
||||
LEFT JOIN AppUsers DO ON W.DogOwnerId = DO.Id
|
||||
LEFT OUTER JOIN AppUserBlocks AUBDW ON AUBDW.BlockedAppUserId = DW.Id AND AUBDW.BlockingAppUserId = DO.Id
|
||||
LEFT OUTER JOIN AppUserBlocks AUBDO ON AUBDO.BlockedAppUserId = DO.Id AND AUBDO.BlockingAppUserId = DW.Id";
|
||||
|
||||
migrationBuilder.Sql($"IF(exists (SELECT 1 FROM sys.objects WHERE Name = '{viewName}')) BEGIN DROP FUNCTION [dbo].[{viewName}] END {Environment.NewLine} GO");
|
||||
migrationBuilder.Sql($"{sql} {Environment.NewLine} GO");
|
||||
}
|
||||
|
||||
/// <inheritdoc />
|
||||
protected override void Down(MigrationBuilder migrationBuilder)
|
||||
{
|
||||
migrationBuilder.DropColumn(
|
||||
name: "PaymentType",
|
||||
table: "Walks");
|
||||
|
||||
var viewName = "tv_WalksWithNames";
|
||||
var sql = @"CREATE FUNCTION tv_WalksWithNames() RETURNS TABLE AS RETURN
|
||||
SELECT W.*,
|
||||
CONCAT(DW.FirstName, ' ' , DW.LastName) AS DogWalkerName, DW.Photo AS DogWalkerPhoto,
|
||||
IsNull(DW.Locked,0) AS DogWalkerLocked, CAST((SELECT CASE WHEN AUBDW.Id IS NOT NULL THEN 1 ELSE 0 END) AS BIT) AS DogWalkerBlocked,
|
||||
CONCAT(DO.FirstName, ' ' , DO.LastName) AS DogOwnerName, DO.Photo AS DogOwnerPhoto,
|
||||
IsNull(DO.Locked,0) AS DogOwnerLocked, CAST((SELECT CASE WHEN AUBDO.Id IS NOT NULL THEN 1 ELSE 0 END) AS BIT) AS DogOwnerBlocked
|
||||
FROM Walks W
|
||||
LEFT JOIN AppUsers DW ON W.DogWalkerId = DW.Id
|
||||
LEFT JOIN AppUsers DO ON W.DogOwnerId = DO.Id
|
||||
LEFT OUTER JOIN AppUserBlocks AUBDW ON AUBDW.BlockedAppUserId = DW.Id AND AUBDW.BlockingAppUserId = DO.Id
|
||||
LEFT OUTER JOIN AppUserBlocks AUBDO ON AUBDO.BlockedAppUserId = DO.Id AND AUBDO.BlockingAppUserId = DW.Id";
|
||||
|
||||
migrationBuilder.Sql($"IF(exists (SELECT 1 FROM sys.objects WHERE Name = '{viewName}')) BEGIN DROP FUNCTION [dbo].[{viewName}] END {Environment.NewLine} GO");
|
||||
migrationBuilder.Sql($"{sql} {Environment.NewLine} GO");
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -7818,6 +7818,9 @@ namespace gehGassi.Persistence.Migrations
|
||||
b.Property<int>("PaymentStatus")
|
||||
.HasColumnType("int");
|
||||
|
||||
b.Property<int>("PaymentType")
|
||||
.HasColumnType("int");
|
||||
|
||||
b.Property<Point>("PickupLocation")
|
||||
.HasColumnType("geography");
|
||||
|
||||
@ -8091,6 +8094,9 @@ namespace gehGassi.Persistence.Migrations
|
||||
b.Property<int>("PaymentStatus")
|
||||
.HasColumnType("int");
|
||||
|
||||
b.Property<int>("PaymentType")
|
||||
.HasColumnType("int");
|
||||
|
||||
b.Property<string>("PickupAddress_AddressLine1")
|
||||
.HasColumnType("nvarchar(max)");
|
||||
|
||||
|
||||
@ -776,7 +776,7 @@ namespace gehGassi.Web.Controllers
|
||||
/// </summary>
|
||||
/// <param name="model">Model</param>
|
||||
/// <returns>Json</returns>
|
||||
[Authorize(Policy = Policies.PowerUserOnly)]
|
||||
[Authorize(Policy = Policies.CustomerOnly)]
|
||||
[HasPermission(Permission.AdvertisementsManage, Permission.AdvertisementsEdit)]
|
||||
[CustomerAuthorize("CustomerId")]
|
||||
[ValidateAntiForgeryToken]
|
||||
|
||||
@ -56,6 +56,7 @@ namespace gehGassi.Web.Controllers.Api
|
||||
[ApiController]
|
||||
[ApiVersion(1)]
|
||||
[ApiVersion(2)]
|
||||
[ApiVersion(3)]
|
||||
[Route("api/account")]
|
||||
[Route("api/v{v:apiVersion}/account")]
|
||||
public class ApiAccountController : ApiBaseController
|
||||
@ -465,6 +466,131 @@ namespace gehGassi.Web.Controllers.Api
|
||||
return BadRequest(CommunicationErrors.Common_Model_Invalid);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Registrieren eines App-Users
|
||||
/// </summary>
|
||||
/// <param name="model">Model</param>
|
||||
/// <returns>HTTP 200 OK wenn erfolgreich</returns>
|
||||
[AllowAnonymous]
|
||||
[HttpPost]
|
||||
[MapToApiVersion(3)]
|
||||
[Route("Register")]
|
||||
public async Task<IActionResult> RegisterV3(RegisterV2Dto model)
|
||||
{
|
||||
var clientOffset = GetClientDateOffset();
|
||||
|
||||
if (ModelState.IsValid)
|
||||
{
|
||||
var user = await _userService.GetByUsernameAsync(model.UserName);
|
||||
if (user == null)
|
||||
{
|
||||
user = _userService.Create();
|
||||
user.Id = Guid.NewGuid().ToString();
|
||||
user.UserName = model.UserName;
|
||||
user.FirstName = model.FirstName;
|
||||
user.LastName = model.LastName;
|
||||
user.FullName = $"{model.FirstName} {model.LastName}";
|
||||
user.RegistrationDate = DateTimeOffset.UtcNow;
|
||||
user.Photo = string.Empty;
|
||||
user.Email = model.UserName;
|
||||
user.EmailConfirmed = !_authOptions.Value.MustConfirmEmail;
|
||||
user.Permissions = PermissionHelper.GetForRole("AppUser").PackPermissionsIntoString();
|
||||
|
||||
var createResult = await _userManager.CreateAsync(user, model.Password);
|
||||
if (createResult.Succeeded)
|
||||
{
|
||||
await _userManager.AddToRoleAsync(user, "AppUser");
|
||||
user = await _userService.GetAsync(user.Id);
|
||||
|
||||
//Nun den AppUser anlegen und dann mit dem Benutzer verknüpfen
|
||||
var appUser = AppUserService.Create();
|
||||
appUser.Type = (AppUserType)model.AppUserType;
|
||||
appUser.Number = AppUserService.GetNextNumber();
|
||||
appUser.FirstName = model.FirstName;
|
||||
appUser.LastName = model.LastName;
|
||||
appUser.Sex = Sex.Undefined;
|
||||
appUser.BirthDate = model.BirthDate;
|
||||
appUser.Photo = string.Empty;
|
||||
appUser.Contact.Email = model.UserName;
|
||||
appUser.Address.City = model.City;
|
||||
appUser.Address.Zip = model.Zip;
|
||||
appUser.Address.CountryCode = model.CountryCode;
|
||||
appUser.Address.State = model.State;
|
||||
appUser.TermsAccepted = true;
|
||||
appUser.TermsAcceptedDate = DateTimeOffset.UtcNow;
|
||||
appUser.PrivacyAccepted = true;
|
||||
appUser.PrivacyAcceptedDate = DateTimeOffset.UtcNow;
|
||||
appUser.Verified = false;
|
||||
appUser.VerifiedDate = null;
|
||||
appUser.PaymentTermsAccepted = false;
|
||||
appUser.PaymentTermsAcceptedDate = null;
|
||||
appUser.NationalityCode = string.Empty;
|
||||
appUser.MainResidenceCode = string.Empty;
|
||||
|
||||
if (appUser.Type == AppUserType.DogWalker)
|
||||
{
|
||||
appUser.PaymentTermsAccepted = false;
|
||||
appUser.PaymentTermsAcceptedDate = null;
|
||||
appUser.NationalityCode = model.NationalityCode;
|
||||
appUser.MainResidenceCode = model.MainResidenceCountryCode;
|
||||
}
|
||||
|
||||
var location = await _geoLocationService.GetLocationAsync($"{model.Zip},{model.City},{model.CountryCode},{model.State}", CultureInfo.CurrentCulture.TwoLetterISOLanguageName);
|
||||
if (location.Success)
|
||||
{
|
||||
var geometryFactory = NtsGeometryServices.Instance.CreateGeometryFactory(srid: 4326);
|
||||
var geoLocation = geometryFactory.CreatePoint(new Coordinate(location.Longitude, location.Latitude));
|
||||
appUser.Location = geoLocation;
|
||||
}
|
||||
|
||||
AppUserService.Add(appUser);
|
||||
await AppUserService.CommitAsync("System");
|
||||
|
||||
user.AppUserId = appUser.Id;
|
||||
await _userService.CommitAsync("System");
|
||||
|
||||
if (appUser.Type != AppUserType.DogOwner)
|
||||
{
|
||||
await AppUserService.CreateWalkerProfileIfNotExistsAsync(appUser.Id);
|
||||
await AppUserService.CommitAsync("System");
|
||||
|
||||
//Nun für den Walker Mangopay User anlegen
|
||||
//var mangoPayResult = await _mangoPayService.CreateOwnerAsync(appUser.Id, false);
|
||||
//if (mangoPayResult.Success)
|
||||
//{
|
||||
// //Wallets anlegen
|
||||
// var walletCreditsResult = await _mangoPayService.CreateWalletAsync(appUser.Id, WalletType.Credits);
|
||||
// var walletFeesResult = await _mangoPayService.CreateWalletAsync(appUser.Id, WalletType.Fees);
|
||||
//}
|
||||
}
|
||||
|
||||
if (_authOptions.Value.MustConfirmEmail)
|
||||
{
|
||||
var code = await _userManager.GenerateEmailConfirmationTokenAsync(user);
|
||||
var callbackUrl = Url.Action("ConfirmEmailApp", "Account", new { userId = user.Id, code = code }, protocol: HttpContext.Request.Scheme);
|
||||
await _emailSender.SendEmailConfirmationAsync(user.UserName, callbackUrl, _localizer, _licenseOptions);
|
||||
}
|
||||
|
||||
return Ok();
|
||||
}
|
||||
else
|
||||
{
|
||||
if (createResult.Errors.FirstOrDefault(c => c.Code == "PwnedPassword") != null)
|
||||
{
|
||||
return BadRequest(CommunicationErrors.Register_Password_Pwned);
|
||||
}
|
||||
if (createResult.Errors.FirstOrDefault(c => c.Code.StartsWith("IdentityError_Password")) != null)
|
||||
{
|
||||
return BadRequest(CommunicationErrors.Register_Password_Rules);
|
||||
}
|
||||
}
|
||||
return BadRequest(CommunicationErrors.Register_Failed);
|
||||
}
|
||||
return BadRequest(CommunicationErrors.Register_Email_Exists);
|
||||
}
|
||||
return BadRequest(CommunicationErrors.Common_Model_Invalid);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Registrieren eines App-Users mittels external Provider
|
||||
/// </summary>
|
||||
@ -958,6 +1084,254 @@ namespace gehGassi.Web.Controllers.Api
|
||||
return BadRequest(CommunicationErrors.Common_Model_Invalid);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Registrieren eines App-Users mittels external Provider
|
||||
/// </summary>
|
||||
/// <param name="model">Model</param>
|
||||
/// <returns>HTTP 200 OK wenn erfolgreich</returns>
|
||||
[AllowAnonymous]
|
||||
[HttpPost]
|
||||
[MapToApiVersion(3)]
|
||||
[Route("RegisterExternal")]
|
||||
public async Task<IActionResult> RegisterExternalV3(RegisterExternalV2Dto model)
|
||||
{
|
||||
var clientOffset = GetClientDateOffset();
|
||||
|
||||
if (ModelState.IsValid)
|
||||
{
|
||||
//Zuerst holen wir nochmal die Infos für den User. Token prüfen... //TODO: Je nach Provider vorgehen. Derzeit nur google. Apple einführen...
|
||||
var tokenValid = false;
|
||||
ExternalLoginGoogleResponse userInfo = null;
|
||||
AppleResponseDto appleResponse = null;
|
||||
|
||||
if (model.LoginProvider == "Google")
|
||||
{
|
||||
HttpStatusCode tokenResponseCode = HttpStatusCode.OK;
|
||||
var httpClient = new HttpClient();
|
||||
try
|
||||
{
|
||||
httpClient.DefaultRequestHeaders.Authorization = new AuthenticationHeaderValue("Bearer", model.AccessToken);
|
||||
var tokenResult = await httpClient.GetAsync($"https://www.googleapis.com/oauth2/v3/userinfo");
|
||||
if (tokenResult.IsSuccessStatusCode)
|
||||
{
|
||||
string jsonString = tokenResult.Content.ReadAsStringAsync().Result;
|
||||
userInfo = JsonSerializer.Deserialize<ExternalLoginGoogleResponse>(jsonString);
|
||||
tokenValid = true;
|
||||
}
|
||||
else
|
||||
{
|
||||
tokenResponseCode = tokenResult.StatusCode;
|
||||
}
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
tokenValid = false;
|
||||
}
|
||||
}
|
||||
else if (model.LoginProvider == "Apple")
|
||||
{
|
||||
var clientSecret = await GenerateAppleClientSecretAsync();
|
||||
var parameters = new List<KeyValuePair<string, string>>
|
||||
{
|
||||
new KeyValuePair<string, string>("client_id", _appleOptions.Value.ClientId),
|
||||
new KeyValuePair<string, string>("client_secret", clientSecret),
|
||||
new KeyValuePair<string, string>("refresh_token", model.AccessToken),
|
||||
new KeyValuePair<string, string>("grant_type", "refresh_token")
|
||||
};
|
||||
|
||||
var httpClient = new HttpClient();
|
||||
try
|
||||
{
|
||||
var tokenResult = await httpClient.PostAsync($"https://appleid.apple.com/auth/token", new FormUrlEncodedContent(parameters));
|
||||
if (tokenResult.IsSuccessStatusCode)
|
||||
{
|
||||
var successResponse = await tokenResult.Content.ReadAsStringAsync();
|
||||
appleResponse = JsonSerializer.Deserialize<AppleResponseDto>(successResponse);
|
||||
tokenValid = true;
|
||||
}
|
||||
else
|
||||
{
|
||||
var errorResponse = await tokenResult.Content.ReadAsStringAsync();
|
||||
_logger.LogError(errorResponse);
|
||||
}
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
tokenValid = false;
|
||||
}
|
||||
}
|
||||
|
||||
if (tokenValid)
|
||||
{
|
||||
var user = await _userService.GetByUsernameAsync(model.UserName);
|
||||
if (user == null)
|
||||
{
|
||||
user = _userService.Create();
|
||||
user.Id = Guid.NewGuid().ToString();
|
||||
user.UserName = model.UserName;
|
||||
user.FirstName = model.FirstName;
|
||||
user.LastName = model.LastName;
|
||||
user.FullName = $"{model.FirstName} {model.LastName}";
|
||||
user.RegistrationDate = DateTimeOffset.UtcNow;
|
||||
user.Photo = string.Empty;
|
||||
user.Email = model.UserName;
|
||||
user.EmailConfirmed = true; //Weil über externen Provider
|
||||
user.Permissions = PermissionHelper.GetForRole("AppUser").PackPermissionsIntoString();
|
||||
|
||||
IdentityResult createResult;
|
||||
if (!string.IsNullOrEmpty(model.Password))
|
||||
createResult = await _userManager.CreateAsync(user, model.Password);
|
||||
else
|
||||
createResult = await _userManager.CreateAsync(user);
|
||||
|
||||
if (createResult.Succeeded)
|
||||
{
|
||||
await _userManager.AddToRoleAsync(user, "AppUser");
|
||||
user = await _userManager.FindByEmailAsync(user.UserName);
|
||||
|
||||
//Nun den AppUser anlegen und dann mit dem Benutzer verknüpfen
|
||||
var appUser = AppUserService.Create();
|
||||
appUser.Type = (AppUserType)model.AppUserType;
|
||||
appUser.Number = AppUserService.GetNextNumber();
|
||||
appUser.FirstName = model.FirstName;
|
||||
appUser.LastName = model.LastName;
|
||||
appUser.Sex = Sex.Undefined;
|
||||
appUser.BirthDate = model.BirthDate;
|
||||
appUser.Photo = string.Empty;
|
||||
appUser.Contact.Email = model.UserName;
|
||||
appUser.Address.City = model.City;
|
||||
appUser.Address.Zip = model.Zip;
|
||||
appUser.Address.CountryCode = model.CountryCode;
|
||||
appUser.Address.State = model.State;
|
||||
appUser.TermsAccepted = true;
|
||||
appUser.TermsAcceptedDate = DateTimeOffset.UtcNow;
|
||||
appUser.PrivacyAccepted = true;
|
||||
appUser.PrivacyAcceptedDate = DateTimeOffset.UtcNow;
|
||||
appUser.Verified = false;
|
||||
appUser.VerifiedDate = null;
|
||||
appUser.PaymentTermsAccepted = false;
|
||||
appUser.PaymentTermsAcceptedDate = null;
|
||||
appUser.NationalityCode = string.Empty;
|
||||
appUser.MainResidenceCode = string.Empty;
|
||||
|
||||
if (appUser.Type == AppUserType.DogWalker)
|
||||
{
|
||||
appUser.PaymentTermsAccepted = false;
|
||||
appUser.PaymentTermsAcceptedDate = null;
|
||||
appUser.NationalityCode = model.NationalityCode;
|
||||
appUser.MainResidenceCode = model.MainResidenceCountryCode;
|
||||
}
|
||||
|
||||
var location = await _geoLocationService.GetLocationAsync($"{model.Zip},{model.City},{model.CountryCode},{model.State}", CultureInfo.CurrentCulture.TwoLetterISOLanguageName);
|
||||
if (location.Success)
|
||||
{
|
||||
var geometryFactory = NtsGeometryServices.Instance.CreateGeometryFactory(srid: 4326);
|
||||
var geoLocation = geometryFactory.CreatePoint(new Coordinate(location.Longitude, location.Latitude));
|
||||
appUser.Location = geoLocation;
|
||||
}
|
||||
|
||||
AppUserService.Add(appUser);
|
||||
await AppUserService.CommitAsync("System");
|
||||
|
||||
user.AppUserId = appUser.Id;
|
||||
await _userManager.UpdateAsync(user);
|
||||
|
||||
if (appUser.Type != AppUserType.DogOwner)
|
||||
{
|
||||
await AppUserService.CreateWalkerProfileIfNotExistsAsync(appUser.Id);
|
||||
await AppUserService.CommitAsync("System");
|
||||
|
||||
//Nun für den Walker Mangopay User anlegen
|
||||
//var mangoPayResult = await _mangoPayService.CreateOwnerAsync(appUser.Id, false);
|
||||
//if (mangoPayResult.Success)
|
||||
//{
|
||||
// //Wallets anlegen
|
||||
// var walletCreditsResult = await _mangoPayService.CreateWalletAsync(appUser.Id, WalletType.Credits);
|
||||
// var walletFeesResult = await _mangoPayService.CreateWalletAsync(appUser.Id, WalletType.Fees);
|
||||
//}
|
||||
}
|
||||
|
||||
//Da wir den User gleich einloggen möchten, geben wir alles nötige zurück
|
||||
var usersClaims = new List<Claim>()
|
||||
{
|
||||
new Claim(ClaimTypes.Name, user.UserName),
|
||||
new Claim(ClaimTypes.GivenName, user.FirstName),
|
||||
new Claim(ClaimTypes.Surname, user.LastName),
|
||||
new Claim(ClaimTypes.NameIdentifier, user.Id.ToString()),
|
||||
new Claim(ClaimTypes.UserData, user.Photo ?? ""),
|
||||
new Claim(ClaimConstants.AppUserIdClaimType, user.AppUserId ?? ""),
|
||||
};
|
||||
|
||||
var roles = await _userManager.GetRolesAsync(user);
|
||||
foreach (var role in roles)
|
||||
{
|
||||
usersClaims.Add(new Claim(ClaimTypes.Role, role));
|
||||
}
|
||||
|
||||
var token = _tokenService.GenerateAccessToken(usersClaims);
|
||||
await _refreshTokenService.RemoveExpiredAsync(user.Id, user.UserName);
|
||||
var refreshToken = _refreshTokenService.Create();
|
||||
refreshToken.UserId = user.Id;
|
||||
_refreshTokenService.Add(refreshToken);
|
||||
await _refreshTokenService.CommitAsync(user.UserName);
|
||||
|
||||
var userDto = Mapper.Map<UserDto>(user);
|
||||
userDto.AccessToken = token;
|
||||
userDto.AccessTokenExpires = DateTimeOffset.UtcNow.AddMinutes(_jwtTokenOptions.Value.TokenMinutes);
|
||||
userDto.RefreshToken = refreshToken.Token;
|
||||
userDto.RefreshTokenExpires = refreshToken.Expires;
|
||||
userDto.AppUserType = (AppUserTypeDto)appUser.Type;
|
||||
|
||||
var roleList = roles.ToList();
|
||||
userDto.Roles = string.Join(";", roleList);
|
||||
|
||||
user.LastLoginDate = DateTimeOffset.UtcNow;
|
||||
await _userManager.UpdateAsync(user);
|
||||
|
||||
if (model.LoginProvider == "Google" && userInfo != null)
|
||||
{
|
||||
var createdUser = await _userManager.FindByEmailAsync(user.UserName);
|
||||
if (createdUser != null)
|
||||
{
|
||||
await _userManager.AddLoginAsync(createdUser, new UserLoginInfo("Google", userInfo.Sub, user.FullName));
|
||||
}
|
||||
}
|
||||
else if (model.LoginProvider == "Apple" && appleResponse != null)
|
||||
{
|
||||
var createdUser = await _userManager.FindByEmailAsync(user.UserName);
|
||||
if (createdUser != null)
|
||||
{
|
||||
var appleToken = new JwtSecurityToken(appleResponse.IdToken);
|
||||
if (appleToken != null)
|
||||
{
|
||||
var appleUserId = appleToken.Claims.First(c => c.Type == "sub").Value;
|
||||
await _userManager.AddLoginAsync(createdUser, new UserLoginInfo("Apple", appleUserId, user.FullName));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return Ok(userDto);
|
||||
}
|
||||
else
|
||||
{
|
||||
if (createResult.Errors.FirstOrDefault(c => c.Code == "PwnedPassword") != null)
|
||||
{
|
||||
return BadRequest(CommunicationErrors.Register_Password_Pwned);
|
||||
}
|
||||
if (createResult.Errors.FirstOrDefault(c => c.Code.StartsWith("Password")) != null)
|
||||
{
|
||||
return BadRequest(CommunicationErrors.Register_Password_Rules);
|
||||
}
|
||||
}
|
||||
return BadRequest(CommunicationErrors.Register_Failed);
|
||||
}
|
||||
return BadRequest(CommunicationErrors.Register_Email_Exists);
|
||||
}
|
||||
return BadRequest(CommunicationErrors.Register_TokenInvalid);
|
||||
}
|
||||
return BadRequest(CommunicationErrors.Common_Model_Invalid);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Anmelden via API. Erstellt ein Access-Token und ein Refresh-Token wenn erfolgreich
|
||||
/// </summary>
|
||||
@ -2041,6 +2415,62 @@ namespace gehGassi.Web.Controllers.Api
|
||||
return NotFound(CommunicationErrors.Common_NotFound);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Setzt den Modus eines App-Users auf "Beides" - von Owner aufgerufen.
|
||||
/// Erstellt keinen MangoPay User und legt keine Wallets an
|
||||
/// </summary>
|
||||
/// <returns>200 OK</returns>
|
||||
[HttpPost]
|
||||
[Route("SetAppUserTypeNoMango")]
|
||||
public async Task<IActionResult> SetAppUserTypeNoMango(SetAppUserTypeExDto model)
|
||||
{
|
||||
var clientOffset = GetClientDateOffset();
|
||||
|
||||
if (User?.Identity != null && User.Identity.IsAuthenticated)
|
||||
{
|
||||
var user = await _userService.GetByUsernameAsync(User.Identity.Name);
|
||||
if (user != null)
|
||||
{
|
||||
if (ModelState.IsValid)
|
||||
{
|
||||
var appUser = await AppUserService.GetAsync(model.Id);
|
||||
if (appUser != null)
|
||||
{
|
||||
if (model.UpdatedAt > appUser.UpdatedAt)
|
||||
{
|
||||
appUser.Type = (AppUserType)model.Type;
|
||||
appUser.NationalityCode = model.NationalityCode;
|
||||
appUser.MainResidenceCode = model.MainResidenceCode;
|
||||
appUser.PaymentTermsAccepted = model.PaymentTermsAccepted;
|
||||
appUser.PaymentTermsAcceptedDate = model.PaymentTermsAcceptedDate;
|
||||
|
||||
appUser.UpdatedAt = model.UpdatedAt;
|
||||
|
||||
await AppUserService.CommitAsync(User.Identity.Name);
|
||||
|
||||
if (appUser.Type != AppUserType.DogOwner)
|
||||
{
|
||||
await AppUserService.CreateWalkerProfileIfNotExistsAsync(appUser.Id);
|
||||
await AppUserService.CommitAsync(User.Identity.Name);
|
||||
}
|
||||
|
||||
var appUserDto = Mapper.Map<AppUserDto>(appUser);
|
||||
var baseAddress = GetBaseAddress();
|
||||
if (!string.IsNullOrWhiteSpace(appUserDto.Photo))
|
||||
{
|
||||
appUserDto.Photo = $"{baseAddress}/file/documents/thumbnails/{200}/{appUserDto.Photo}";
|
||||
}
|
||||
return Ok(appUserDto);
|
||||
}
|
||||
}
|
||||
return NotFound(CommunicationErrors.Common_NotFound);
|
||||
}
|
||||
return BadRequest(CommunicationErrors.Common_Model_Invalid);
|
||||
}
|
||||
}
|
||||
return NotFound(CommunicationErrors.Common_NotFound);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Hinzufügen eines PaymentUsers zu einem AppUser
|
||||
/// </summary>
|
||||
|
||||
@ -43,6 +43,7 @@ namespace gehGassi.Web.Controllers.Api
|
||||
[Authorize(AuthenticationSchemes = JwtBearerDefaults.AuthenticationScheme)]
|
||||
[ApiController]
|
||||
[ApiVersion(1)]
|
||||
[ApiVersion(2)]
|
||||
[Route("api/walks")]
|
||||
[Route("api/v{v:apiVersion}/walks")]
|
||||
public class ApiWalksController : ApiBaseController
|
||||
@ -954,6 +955,120 @@ namespace gehGassi.Web.Controllers.Api
|
||||
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 = model.PaymentType != null ? (WalkPaymentType)model.PaymentType : WalkPaymentType.MangoPay;
|
||||
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>
|
||||
@ -2224,6 +2339,128 @@ namespace gehGassi.Web.Controllers.Api
|
||||
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>
|
||||
@ -2604,6 +2841,190 @@ namespace gehGassi.Web.Controllers.Api
|
||||
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>
|
||||
@ -2798,6 +3219,205 @@ namespace gehGassi.Web.Controllers.Api
|
||||
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>
|
||||
@ -2947,6 +3567,102 @@ namespace gehGassi.Web.Controllers.Api
|
||||
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 = model.PaymentType != null ? (WalkPaymentType)model.PaymentType : WalkPaymentType.MangoPay;
|
||||
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>
|
||||
@ -3031,6 +3747,92 @@ namespace gehGassi.Web.Controllers.Api
|
||||
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 = model.PaymentType != null ? (WalkPaymentType)model.PaymentType : WalkPaymentType.MangoPay;
|
||||
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>
|
||||
@ -3071,6 +3873,47 @@ namespace gehGassi.Web.Controllers.Api
|
||||
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>
|
||||
|
||||
@ -98,6 +98,8 @@ namespace gehGassi.Web.Controllers
|
||||
whereFilterPredicate.value = (WalkStatus)((int)((long)whereFilterPredicate.value));
|
||||
if (whereFilterPredicate.Field == "paymentStatus")
|
||||
whereFilterPredicate.value = (PaymentStatus)((int)((long)whereFilterPredicate.value));
|
||||
if (whereFilterPredicate.Field == "paymentType")
|
||||
whereFilterPredicate.value = (WalkPaymentType)((int)((long)whereFilterPredicate.value));
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -120,6 +122,7 @@ namespace gehGassi.Web.Controllers
|
||||
itemVm.ServiceTypeText = itemVm.ServiceType.GetDisplayName(AnnotationsLocalizer);
|
||||
itemVm.StatusText = itemVm.Status.GetDisplayName(AnnotationsLocalizer);
|
||||
itemVm.PaymentStatusText = itemVm.PaymentStatus.GetDisplayName(AnnotationsLocalizer);
|
||||
itemVm.PaymentTypeText = itemVm.PaymentType.GetDisplayName(AnnotationsLocalizer);
|
||||
}
|
||||
|
||||
//FilterPreview?
|
||||
|
||||
@ -135,6 +135,9 @@ namespace gehGassi.Web.Mapper
|
||||
CreateMap<PaymentStatus, PaymentStatusVm>();
|
||||
CreateMap<PaymentStatusVm, PaymentStatus>();
|
||||
|
||||
CreateMap<WalkPaymentType, WalkPaymentTypeVm>();
|
||||
CreateMap<WalkPaymentTypeVm, WalkPaymentType>();
|
||||
|
||||
CreateMap<OrderStatus, OrderStatusVm>();
|
||||
CreateMap<OrderStatusVm, OrderStatus>();
|
||||
|
||||
@ -638,6 +641,9 @@ namespace gehGassi.Web.Mapper
|
||||
CreateMap<PaymentStatus, PaymentStatusDto>();
|
||||
CreateMap<PaymentStatusDto, PaymentStatus>();
|
||||
|
||||
CreateMap<WalkPaymentType, WalkPaymentTypeDto>();
|
||||
CreateMap<WalkPaymentTypeDto, WalkPaymentType>();
|
||||
|
||||
CreateMap<RatingTarget, RatingTargetDto>();
|
||||
CreateMap<RatingTargetDto, RatingTarget>();
|
||||
|
||||
|
||||
@ -378,6 +378,23 @@ namespace gehGassi.Web.Models
|
||||
RefundendAndPayed = 60
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Zahlungsart für einen Walk
|
||||
/// </summary>
|
||||
public enum WalkPaymentTypeVm
|
||||
{
|
||||
/// <summary>
|
||||
/// Mit MangoPay bezahlen (z.B. Kreditkarte)
|
||||
/// </summary>
|
||||
[Display(Name = "WalkPaymentType_MangoPay")]
|
||||
MangoPay = 1,
|
||||
/// <summary>
|
||||
/// Barzahlung
|
||||
/// </summary>
|
||||
[Display(Name = "WalkPaymentType_Cash")]
|
||||
Cash = 10
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Status einer Bestellung
|
||||
/// </summary>
|
||||
|
||||
@ -220,6 +220,11 @@ namespace gehGassi.Web.Models
|
||||
/// </summary>
|
||||
public PaymentStatusVm PaymentStatus { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// Zahlungsart des Walks
|
||||
/// </summary>
|
||||
public WalkPaymentTypeVm PaymentType { get; set; }
|
||||
|
||||
#endregion
|
||||
|
||||
/// <summary>
|
||||
@ -380,6 +385,16 @@ namespace gehGassi.Web.Models
|
||||
/// </summary>
|
||||
public string PaymentStatusText { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// Welche Art von Bezahlung wurde verwendet
|
||||
/// </summary>
|
||||
public WalkPaymentTypeVm PaymentType { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// Welche Art von Bezahlung wurde verwendet
|
||||
/// </summary>
|
||||
public string PaymentTypeText { get; set; }
|
||||
|
||||
#endregion
|
||||
|
||||
/// <summary>
|
||||
|
||||
@ -229,7 +229,15 @@ export enum PaymentStatus {
|
||||
/**Entwertet */
|
||||
Voided = 50,
|
||||
/**Rückerstattet gehgassi */
|
||||
RefundendAndPayed = 60,
|
||||
RefundendAndPayed = 60
|
||||
}
|
||||
|
||||
/**Zahlungsarten Walk */
|
||||
export enum WalkPaymentType {
|
||||
/**MangoPay */
|
||||
MangoPay = 1,
|
||||
/**Cash */
|
||||
Cash = 10
|
||||
}
|
||||
|
||||
/**Geoeinschränkungen für Listungen und Werbungen */
|
||||
@ -2473,6 +2481,9 @@ export class WalkWithNamesListItem extends SyncEntity {
|
||||
/**Zahlungsstatus des Walks */
|
||||
paymentStatus: PaymentStatus;
|
||||
|
||||
/**Zahlungsart des Walks */
|
||||
paymentType: WalkPaymentType;
|
||||
|
||||
/**Datum der Erstellung des Walks */
|
||||
created: Date | string;
|
||||
}
|
||||
|
||||
@ -15,6 +15,7 @@ import WalkType = Models.WalkType;
|
||||
import WalkStatus = Models.WalkStatus;
|
||||
import WalkServiceType = Models.WalkServiceType;
|
||||
import PaymentStatus = Models.PaymentStatus;
|
||||
import WalkPaymentType = Models.WalkPaymentType;
|
||||
|
||||
|
||||
class WalksModule {
|
||||
@ -40,6 +41,9 @@ class WalksModule {
|
||||
private _paymentStatusList;
|
||||
private _filterPaymentStatus: DropDownList;
|
||||
|
||||
private _paymentTypeList;
|
||||
private _filterPaymentType: DropDownList;
|
||||
|
||||
constructor() {
|
||||
this._global = Global.getInstance();
|
||||
this._eventManager = EventManager.getInstance();
|
||||
@ -95,6 +99,10 @@ class WalksModule {
|
||||
{ value: PaymentStatus.Voided, text: self._localizationMananger.get("PaymentStatus_Voided") },
|
||||
{ value: PaymentStatus.RefundendAndPayed, text: self._localizationMananger.get("PaymentStatus_RefundendAndPayed") }];
|
||||
|
||||
self._paymentTypeList = [
|
||||
{ value: WalkPaymentType.MangoPay, text: self._localizationMananger.get("WalkPaymentType_MangoPay")},
|
||||
{ value: WalkPaymentType.Cash, text: self._localizationMananger.get("WalkPaymentType_Cash") }];
|
||||
|
||||
self._dataManager = new DataManager({
|
||||
url: <string>$(self.prefix("#jsGetUrl")).val(),
|
||||
adaptor: new UrlAdaptor(),
|
||||
@ -201,6 +209,32 @@ class WalksModule {
|
||||
}
|
||||
}
|
||||
},
|
||||
{
|
||||
field: "paymentType", headerText: self._localizationMananger.get("Walk_PaymentType"), type: "number", template: "${paymentTypeText}",
|
||||
filter: {
|
||||
ui: {
|
||||
create: (args: { target: Element, column: Object }) => {
|
||||
let flValInput: HTMLElement = createElement("input", { className: "flm-input" });
|
||||
args.target.appendChild(flValInput);
|
||||
self._filterPaymentType = new DropDownList({
|
||||
dataSource: new DataManager(self._paymentTypeList),
|
||||
fields: { text: "text", value: "value" },
|
||||
placeholder: self._localizationMananger.get("Common_Select"),
|
||||
popupHeight: "200px"
|
||||
});
|
||||
self._filterPaymentType.appendTo(flValInput);
|
||||
},
|
||||
write: (args: {
|
||||
column: Object, target: Element, parent: any, filteredValue: number | string
|
||||
}) => {
|
||||
self._filterPaymentType.value = args.filteredValue;
|
||||
},
|
||||
read: (args: { target: Element, column: any, operator: string, fltrObj: Filter }) => {
|
||||
args.fltrObj.filterByColumn(args.column.field, args.operator, self._filterPaymentType.value);
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
{
|
||||
field: "paymentStatus", headerText: self._localizationMananger.get("Walk_PaymentStatus"), type: "number", template: "${paymentStatusText}",
|
||||
filter: {
|
||||
|
||||
@ -65,6 +65,13 @@
|
||||
<div class="h5 mb-1">@annotationsLocalizer["Walk_Status"]</div>
|
||||
@Model.Status.GetDisplayName(annotationsLocalizer)
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="row mb-3">
|
||||
<div class="col-sm-3">
|
||||
<div class="h5 mb-1">@annotationsLocalizer["Walk_PaymentType"]</div>
|
||||
@Model.PaymentType.GetDisplayName(annotationsLocalizer)
|
||||
</div>
|
||||
<div class="col-sm-3">
|
||||
<div class="h5 mb-1">@annotationsLocalizer["Walk_PaymentStatus"]</div>
|
||||
@Model.PaymentStatus.GetDisplayName(annotationsLocalizer)
|
||||
|
||||
@ -22,10 +22,10 @@
|
||||
"LicenseOptions": {
|
||||
"Address": "https://gehgassi.com",
|
||||
"Software": "gehgassi",
|
||||
"Version": "1.0.99"
|
||||
"Version": "1.0.100"
|
||||
},
|
||||
"SystemJsOptions": {
|
||||
"FileVersion": "1.0.99"
|
||||
"FileVersion": "1.0.100"
|
||||
},
|
||||
"SessionSettings": {
|
||||
"TimeOut": "60",
|
||||
|
||||
@ -23,10 +23,10 @@
|
||||
"LicenseOptions": {
|
||||
"Address": "https://creativeBITS.com",
|
||||
"Software": "gehgassi",
|
||||
"Version": "1.0.99"
|
||||
"Version": "1.0.100"
|
||||
},
|
||||
"SystemJsOptions": {
|
||||
"FileVersion": "1.0.99"
|
||||
"FileVersion": "1.0.100"
|
||||
},
|
||||
"SessionSettings": {
|
||||
"TimeOut": "60",
|
||||
|
||||
@ -22,10 +22,10 @@
|
||||
"LicenseOptions": {
|
||||
"Address": "https://gehGassi.creativeBITS.eu",
|
||||
"Software": "gehgassi",
|
||||
"Version": "1.0.99"
|
||||
"Version": "1.0.100"
|
||||
},
|
||||
"SystemJsOptions": {
|
||||
"FileVersion": "1.0.99"
|
||||
"FileVersion": "1.0.100"
|
||||
},
|
||||
"SessionSettings": {
|
||||
"TimeOut": "60",
|
||||
|
||||
@ -23,10 +23,10 @@
|
||||
"LicenseOptions": {
|
||||
"Address": "https://creativeBITS.com",
|
||||
"Software": "gehgassi",
|
||||
"Version": "1.0.99"
|
||||
"Version": "1.0.100"
|
||||
},
|
||||
"SystemJsOptions": {
|
||||
"FileVersion": "1.0.99"
|
||||
"FileVersion": "1.0.100"
|
||||
},
|
||||
"SessionSettings": {
|
||||
"TimeOut": "60",
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user