Compare commits

..

No commits in common. "features/auto-payout-tool" and "master" have entirely different histories.

11 changed files with 42 additions and 325 deletions

View File

@ -3696,19 +3696,6 @@ namespace gehGassi.Core.Interfaces
/// <param name="appUserId">Id des AppUsers</param>
/// <returns>Liste von Wallets</returns>
Task<List<Wallet>> GetAllAsync(string appUserId);
/// <summary>
/// Gibt eine Liste aller Wallets mit positivem Kontostand zurück
/// </summary>
/// <param name="type">Wallet typ</param>
/// <returns>Liste von Wallets</returns>
Task<List<Wallet>> GetAllWithPositiveBalanceAsync(WalletType type);
/// <summary>
/// Gibt eine Liste aller Wallets mit positivem Kontostand zurück
/// </summary>
/// <returns>Liste von Wallets</returns>
Task<List<Wallet>> GetAllWithPositiveBalanceAsync();
}
/// <summary>

View File

@ -1,11 +1,10 @@
using gehGassi.Core.Interfaces;
using gehGassi.Domain.Common;
using gehGassi.Domain.Dogs;
using gehGassi.Domain.Payment;
using System;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Threading.Tasks;
using gehGassi.Core.Interfaces;
using gehGassi.Domain.Common;
using gehGassi.Domain.Payment;
namespace gehGassi.Core.Services
{
@ -71,24 +70,5 @@ namespace gehGassi.Core.Services
{
return (await Repository.FindAsync(c => c.AppUserId == appUserId).ConfigureAwait(false)).ToList();
}
/// <summary>
/// Gibt eine Liste aller Wallets mit positivem Kontostand zurück
/// </summary>
/// <param name="type">Wallet typ</param>
/// <returns>Liste von Wallets</returns>
public async Task<List<Wallet>> GetAllWithPositiveBalanceAsync(WalletType type)
{
return (await Repository.FindAsync(c => c.Type == type && c.Balance > 0).ConfigureAwait(false)).ToList();
}
/// <summary>
/// Gibt eine Liste aller Wallets mit positivem Kontostand zurück
/// </summary>
/// <returns>Liste von Wallets</returns>
public async Task<List<Wallet>> GetAllWithPositiveBalanceAsync()
{
return (await Repository.FindAsync(c => c.Balance > 0).ConfigureAwait(false)).ToList();
}
}
}

View File

@ -820,11 +820,10 @@ namespace gehGassi.Web.Controllers.Api
}
//Wenn der erfolgreiche KYC-Check eines AppUsers nicht mindestens 48 Stunden zurückliegt, dann keine Auszahlung
//TODO: Prüfen ob nicht wieder aktiviert werden soll!
//if (appUser.KycPassedDate.HasValue && appUser.KycPassedDate.Value > DateTimeOffset.UtcNow.AddHours(-48))
//{
// return BadRequest(CommunicationErrors.PayOut_Failed);
//}
if (appUser.KycPassedDate.HasValue && appUser.KycPassedDate.Value > DateTimeOffset.UtcNow.AddHours(-48))
{
return BadRequest(CommunicationErrors.PayOut_Failed);
}
//Wenn mmehr als 200 Euro, dann blockieren
//TODO: Überprüfen ob das für die App-User passt.

View File

@ -1,20 +1,26 @@
using AutoMapper;
using System;
using System.Collections.Generic;
using System.Dynamic;
using System.IO;
using System.Linq;
using System.Text.Json;
using System.Threading.Tasks;
using AutoMapper;
using gehGassi.Core.Interfaces;
using gehGassi.Core.Services;
using gehGassi.Domain.Common;
using gehGassi.Domain.Dogs;
using gehGassi.Domain.Users;
using gehGassi.Web.Auth;
using gehGassi.Web.Models;
using gehGassi.Web.Helper;
using Microsoft.AspNetCore.Authorization;
using Microsoft.AspNetCore.Mvc;
using Microsoft.AspNetCore.Routing;
using Microsoft.Extensions.DependencyInjection;
using Microsoft.Extensions.Localization;
using System;
using System.Collections.Generic;
using System.Dynamic;
using System.Linq;
using System.Text.Json;
using System.Threading.Tasks;
using gehGassi.Dto.Payment;
using SixLabors.ImageSharp;
using SixLabors.ImageSharp.Advanced;
using SixLabors.ImageSharp.Processing;
namespace gehGassi.Web.Controllers
{
@ -42,7 +48,6 @@ namespace gehGassi.Web.Controllers
private readonly IDeviceService _deviceService;
private readonly IMessageService _messageService;
private readonly IAppUserReportService _appUserReportService;
private readonly IPayoutService _payoutService;
/// <summary>
/// Erstellt eine Instanz
@ -65,11 +70,9 @@ namespace gehGassi.Web.Controllers
/// <param name="deviceService">Instanz eines IDeviceService</param>
/// <param name="messageService">Instanz eines IMessageService</param>
/// <param name="appUserReportService">Instanz eines IAppUserReportService</param>
/// <param name="payoutService">Instanz eines IPayoutService</param>
public ToolsController(IMapper mapper, IStringLocalizer<ToolsController> localizer, IFileService fileService, IFileShareService fileShareService, IMangoPayService mangoPayService, IPushNotificationService pushNotificationService,
IAppUserService appUserService, IWalletService walletService, IWalkService walkService, IRatingService ratingService, ITransactionFeeService transactionFeeService, IRefreshTokenService refreshTokenService,
IUserService userService, IFavouriteService favouriteService, ISystemMessageService systemMessageService, IDeviceService deviceService, IMessageService messageService, IAppUserReportService appUserReportService,
IPayoutService payoutService)
IUserService userService, IFavouriteService favouriteService, ISystemMessageService systemMessageService, IDeviceService deviceService, IMessageService messageService, IAppUserReportService appUserReportService)
{
_mapper = mapper;
_localizer = localizer;
@ -89,7 +92,6 @@ namespace gehGassi.Web.Controllers
_deviceService = deviceService;
_messageService = messageService;
_appUserReportService = appUserReportService;
_payoutService = payoutService;
}
public async Task<IActionResult> TestMango()
@ -166,7 +168,6 @@ namespace gehGassi.Web.Controllers
else
walk.PaymentStatus = PaymentStatus.Voided;
}
await _walkService.CommitAsync("System");
}
@ -242,7 +243,6 @@ namespace gehGassi.Web.Controllers
feeDecimal += gehGassiFee.Fixed;
}
}
if (feeDecimal > 0)
{
fee = (long)(feeDecimal * 100);
@ -303,7 +303,6 @@ namespace gehGassi.Web.Controllers
{
_walletService.Remove(wallet);
}
await _walletService.CommitAsync("System");
return Ok();
@ -330,7 +329,7 @@ namespace gehGassi.Web.Controllers
//Es gibt noch keinen MangopayUser für DogWalker oder BOTH!!!
if (string.IsNullOrWhiteSpace(appUser.NationalityCode))
appUser.NationalityCode = appUser.Address.CountryCode;
if (string.IsNullOrEmpty(appUser.MainResidenceCode))
if(string.IsNullOrEmpty(appUser.MainResidenceCode))
appUser.MainResidenceCode = appUser.Address.CountryCode;
if (!appUser.PaymentTermsAccepted || appUser.PaymentTermsAcceptedDate == null)
{
@ -349,18 +348,18 @@ namespace gehGassi.Web.Controllers
//Wallets anlegen
var walletFees = await _mangoPayService.CreateWalletAsync(appUser.Id, WalletType.Fees);
if (walletFees.Success)
if(walletFees.Success)
System.Diagnostics.Debug.WriteLine($"{appUser.FirstName} {appUser.LastName}: Es wurde ein neues Fee-Wallet angelegt");
var walletCredits = await _mangoPayService.CreateWalletAsync(appUser.Id, WalletType.Credits);
if (walletCredits.Success)
if(walletCredits.Success)
System.Diagnostics.Debug.WriteLine($"{appUser.FirstName} {appUser.LastName}: Es wurde ein neues Credit-Wallet angelegt");
}
else
{
System.Diagnostics.Debug.WriteLine($"{appUser.FirstName} {appUser.LastName} es konnte kein MangoPay-User angelegt werden.");
if (!string.IsNullOrWhiteSpace(createResult.ErrorMessage))
if(!string.IsNullOrWhiteSpace(createResult.ErrorMessage))
System.Diagnostics.Debug.WriteLine(createResult.ErrorMessage);
if (createResult.ErrorMessages != null)
if(createResult.ErrorMessages != null)
foreach (var error in createResult.ErrorMessages)
System.Diagnostics.Debug.WriteLine($"{error.Key} --> {error.Value}");
}
@ -430,7 +429,7 @@ namespace gehGassi.Web.Controllers
{
//Wallet anlegen
var walletCredits = await _mangoPayService.CreateWalletAsync(appUser.Id, WalletType.Credits);
if (walletCredits.Success)
if(walletCredits.Success)
System.Diagnostics.Debug.WriteLine($"{appUser.FirstName} {appUser.LastName}: Es wurde ein neues Credit-Wallet angelegt");
else
System.Diagnostics.Debug.WriteLine($"{appUser.FirstName} {appUser.LastName}: Es konnte kein neues Credit-Wallet angelegt werde");
@ -453,7 +452,6 @@ namespace gehGassi.Web.Controllers
System.Diagnostics.Debug.WriteLine($"{appUser.FirstName} {appUser.LastName}: Es konnte kein neues Credit-Wallet angelegt werde");
}
}
var feeWallet = wallets.FirstOrDefault(c => c.Type == WalletType.Fees);
if (feeWallet == null)
{
@ -594,151 +592,10 @@ namespace gehGassi.Web.Controllers
{
await _ratingService.UpdateRatingStatisticsAsync(ratingTargetToUpdate.Item1, ratingTargetToUpdate.Item2);
}
await _ratingService.CommitAsync(User.Identity.Name);
}
return View(model);
}
/// <summary>
/// Tool zum automatischen Auszahlen von Guthaben wenn dies möglich ist
/// </summary>
/// <returns>Task</returns>
public async Task<IActionResult> AutoPayout()
{
var model = new List<AutoPayoutVm>();
//1. alle Wallets mit Guthaben holen
var wallets = await _walletService.GetAllWithPositiveBalanceAsync();
//2. nun prüfen ob der wallet status mit dem bei mangoPay übereinstimmt
foreach (var wallet in wallets)
{
var balanceResponse = await _mangoPayService.GetWalletBalanceAsync(wallet.WalletId);
if (balanceResponse.Success)
{
wallet.Balance = balanceResponse.Value;
wallet.UpdatedAt = DateTimeOffset.UtcNow;
await _walletService.CommitAsync("System", true);
}
}
//Nun die wallets erneut holen
wallets = await _walletService.GetAllWithPositiveBalanceAsync();
foreach (var wallet in wallets)
{
//App user zum Wallet holen
var appUser = await _appUserService.GetAsync(wallet.AppUserId);
if (appUser != null)
{
//Nun prüfen ob berechtig für eine Auszahlung
if (appUser.Locked)
continue;
if (!appUser.KycPassed)
continue;
var getBankAccountResult = await _mangoPayService.GetBankAccountAsync(appUser.Id, appUser.PaymentId, appUser.BankId);
if (getBankAccountResult.Success)
{
var viewModel = new AutoPayoutVm
{
AppUser = appUser,
Wallet = wallet
};
model.Add(viewModel);
}
}
}
return View(model);
}
/// <summary>
/// Run Auto Payout
/// </summary>
/// <returns></returns>
public async Task<IActionResult> RunAutoPayout()
{
var model = new List<RunAutoPayoutVm>();
//1. alle Wallets mit Guthaben holen
var wallets = await _walletService.GetAllWithPositiveBalanceAsync();
foreach (var wallet in wallets)
{
try
{
//App user zum Wallet holen
var appUser = await _appUserService.GetAsync(wallet.AppUserId);
if (appUser != null)
{
//Nun prüfen ob berechtig für eine Auszahlung
if (appUser.Locked)
continue;
if (!appUser.KycPassed)
continue;
var getBankAccountResult = await _mangoPayService.GetBankAccountAsync(appUser.Id, appUser.PaymentId, appUser.BankId);
if (getBankAccountResult.Success)
{
var iban = string.Empty;
if (!string.IsNullOrWhiteSpace(getBankAccountResult.Value.Iban))
iban = getBankAccountResult.Value.Iban;
var bic = string.Empty;
if (!string.IsNullOrWhiteSpace(getBankAccountResult.Value.Bic))
bic = getBankAccountResult.Value.Bic;
if (iban.Length >= 4)
{
iban = iban.Substring(iban.Length - 4);
}
if (bic.Length >= 4)
{
bic = bic.Substring(bic.Length - 4);
}
//Auszahlen
var ammount = wallet.Balance;
var payout = _payoutService.Create(appUser.Id, appUser.PaymentId, "", wallet.Id, wallet.WalletId, appUser.BankId, iban, bic, ammount, "EUR");
var payoutResult = await _mangoPayService.CreatePayoutAsync(appUser.PaymentId, wallet.WalletId, appUser.BankId, ammount, $"Payout_{payout.Id}");
if (payoutResult.Success)
{
payout.MangoPayId = payoutResult.Value.PayoutId;
payout.Status = payoutResult.Value.Status;
payout.ResultCode = payoutResult.Value.ResultCode;
payout.ResultMessage = payoutResult.Value.ResultMessage;
payout.ExecutionDate = payoutResult.Value.ExecutionDate;
payout.UpdatedAt = DateTimeOffset.UtcNow;
_payoutService.Add(payout);
await _payoutService.CommitAsync(User.Identity.Name);
var dto = _mapper.Map<PayoutDto>(payout);
var item = new RunAutoPayoutVm()
{
Wallet = wallet,
AppUser = appUser,
PayoutDto = dto
};
model.Add(item);
}
}
}
}
catch (Exception ex)
{
System.Diagnostics.Debug.WriteLine(ex.Message);
}
}
return View(model);
}
}
}

View File

@ -1,22 +0,0 @@
using gehGassi.Domain.Dogs;
using gehGassi.Domain.Payment;
using gehGassi.Dto.Payment;
namespace gehGassi.Web.Models
{
/// <summary>
/// Viewmodel für das Autopayout tool
/// </summary>
public class AutoPayoutVm
{
public Wallet Wallet { get; set; }
public AppUser AppUser { get; set; }
}
public class RunAutoPayoutVm
{
public Wallet Wallet { get; set; }
public AppUser AppUser { get; set; }
public PayoutDto PayoutDto { get; set; }
}
}

View File

@ -1,38 +0,0 @@
@using gehGassi.Permissions
@using gehGassi.Web.Helper
@using Microsoft.AspNetCore.Mvc.Localization
@model List<gehGassi.Web.Models.AutoPayoutVm>;
@inject IViewLocalizer Localizer
@{
ViewData["Title"] = Localizer["Menu_Tools"];
}
@section pageTitle {
<a href="@Url.Action("Index", "Home")">@Localizer["Menu_Tools"]</a>
}
<section id="autoPayoutListContainer">
<table class="table table-striped">
<thead>
<tr>
<th>App user</th>
<th>Type</th>
<th>Balance</th>
</tr>
</thead>
<tbody>
@foreach (var item in Model)
{
<tr>
<td>@item.AppUser.FirstName @item.AppUser.LastName</td>
<td>@item.Wallet.Type.ToString()</td>
<td>€ @((item.Wallet.Balance / 100).ToString("N2"))</td>
</tr>
}
</tbody>
</table>
<div class="text-center mt-5">
<a href="@Url.Action("RunAutoPayout", "Tools")" class="btn btn-primary">Run Auto Payout</a>
</div>
</section>

View File

@ -1,46 +0,0 @@
@using gehGassi.Permissions
@using gehGassi.Web.Helper
@using Microsoft.AspNetCore.Mvc.Localization
@model List<gehGassi.Web.Models.RunAutoPayoutVm>;
@inject IViewLocalizer Localizer
@{
ViewData["Title"] = Localizer["Menu_Tools"];
}
@section pageTitle {
<a href="@Url.Action("Index", "Home")">@Localizer["Menu_Tools"]</a>
}
<section id="autoPayoutListContainer">
<table class="table table-striped">
<thead>
<tr>
<th>App user</th>
<th>Balance before</th>
<th>IBAN</th>
<th>BIC</th>
<th>Status</th>
<th>Ammount</th>
<th>Result code</th>
<th>Result message</th>
</tr>
</thead>
<tbody>
@foreach (var item in Model)
{
<tr>
<td>@item.AppUser.FirstName @item.AppUser.LastName</td>
<td>€ @((item.Wallet.Balance / 100).ToString("N2"))</td>
<td>@item.PayoutDto.Iban</td>
<td>@item.PayoutDto.Bic</td>
<td>@item.PayoutDto.Status.ToString()</td>
<td>€ @((item.PayoutDto.Ammount / 100).ToString("N2"))</td>
<td>@item.PayoutDto.ResultCode</td>
<td>@item.PayoutDto.ResultMessage</td>
</tr>
}
</tbody>
</table>
</section>

View File

@ -107,7 +107,7 @@
"AutoConfirm": true,
"ConfirmationMinutes": 10080,
"ConfirmationReminderMinutes": 1440,
"MinPayoutAmmount": 1
"MinPayoutAmmount": 1000
},
"GeoLocationOptions": {
"BaseUri": "https://nominatim.openstreetmap.org/",

View File

@ -108,7 +108,7 @@
"AutoConfirm": true,
"ConfirmationMinutes": 10080,
"ConfirmationReminderMinutes": 1440,
"MinPayoutAmmount": 1
"MinPayoutAmmount": 1000
},
"GeoLocationOptions": {
"BaseUri": "https://nominatim.openstreetmap.org/",

View File

@ -107,7 +107,7 @@
"AutoConfirm": true,
"ConfirmationMinutes": 10080,
"ConfirmationReminderMinutes": 1440,
"MinPayoutAmmount": 1
"MinPayoutAmmount": 1000
},
"GeoLocationOptions": {
"BaseUri": "https://nominatim.openstreetmap.org/",

View File

@ -108,7 +108,7 @@
"AutoConfirm": true,
"ConfirmationMinutes": 10080,
"ConfirmationReminderMinutes": 1440,
"MinPayoutAmmount": 1
"MinPayoutAmmount": 1000
},
"GeoLocationOptions": {
"BaseUri": "https://nominatim.openstreetmap.org/",