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.Helper; using Microsoft.AspNetCore.Authorization; using Microsoft.AspNetCore.Mvc; using Microsoft.AspNetCore.Routing; using Microsoft.Extensions.DependencyInjection; using Microsoft.Extensions.Localization; using SixLabors.ImageSharp; using SixLabors.ImageSharp.Advanced; using SixLabors.ImageSharp.Processing; namespace gehGassi.Web.Controllers { /// /// Controller der Tools für CB zur Verfügung stellt /// [Authorize(Policy = Policies.AdministratorOnly)] public class ToolsController : BaseController { private readonly IMapper _mapper; private readonly IStringLocalizer _localizer; private readonly IFileService _fileService; private readonly IFileShareService _fileShareService; private readonly IMangoPayService _mangoPayService; private readonly IPushNotificationService _pushNotificationService; private readonly IAppUserService _appUserService; private readonly IWalletService _walletService; private readonly IWalkService _walkService; private readonly IRatingService _ratingService; private readonly ITransactionFeeService _transactionFeeService; private readonly IRefreshTokenService _refreshTokenService; private readonly IUserService _userService; private readonly IFavouriteService _favouriteService; private readonly ISystemMessageService _systemMessageService; private readonly IDeviceService _deviceService; private readonly IMessageService _messageService; private readonly IAppUserReportService _appUserReportService; /// /// Erstellt eine Instanz /// /// Instanz eines IMapper /// Instanz eines IStringLocalizer /// Instanz eines IFileService /// Instanz eines IFileShareService /// Instanz eines IMangoPayService /// Instanz eines IPushNotificationService /// Instanz eines IAppUserService /// Instanz eines IWalletService /// Instanz eines IWalkService /// Instanz eines IRatingService /// Instanz eines ITransactionFeeService /// Instanz eines IRefreshTokenService /// Instanz eines IUserService /// Instanz eines IFavouriteService /// Instanz eines ISystemMessageService /// Instanz eines IDeviceService /// Instanz eines IMessageService /// Instanz eines IAppUserReportService public ToolsController(IMapper mapper, IStringLocalizer 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) { _mapper = mapper; _localizer = localizer; _fileService = fileService; _fileShareService = fileShareService; _mangoPayService = mangoPayService; _pushNotificationService = pushNotificationService; _appUserService = appUserService; _walletService = walletService; _walkService = walkService; _ratingService = ratingService; _transactionFeeService = transactionFeeService; _refreshTokenService = refreshTokenService; _userService = userService; _favouriteService = favouriteService; _systemMessageService = systemMessageService; _deviceService = deviceService; _messageService = messageService; _appUserReportService = appUserReportService; } public async Task TestMango() { await _mangoPayService.TestAsync(); //var userId = await _mangoPayService.CreateOwnerAsync("2d23b001907946eba8aaa46aa46ef8a6"); //var updateSuccess = await _mangoPayService.UpdateOwnerAsync("2d23b001907946eba8aaa46aa46ef8a6"); //var walletFees = await _mangoPayService.CreateWalletAsync("2d23b001907946eba8aaa46aa46ef8a6", WalletType.Fees); //var walletCredits = await _mangoPayService.CreateWalletAsync("2d23b001907946eba8aaa46aa46ef8a6", WalletType.Credits); //var balance1 = await _mangoPayService.GetBalanceAsync("2d23b001907946eba8aaa46aa46ef8a6", WalletType.Fees); //var balance2 = await _mangoPayService.GetBalanceAsync("2d23b001907946eba8aaa46aa46ef8a6", WalletType.Credits); //var balanceResult = await _mangoPayService.GetWalletBalanceAsync("162617747"); //var redirectUrl = await _mangoPayService.CreatePayInMaeostroAsync("162609301", "162617747", 10000); return Ok(); //var redirectUrl = await _mangoPayService.CreatePayInMaeostroAsync("160864861", "160911719", 1000); //return Redirect(redirectUrl); } public async Task Hub() { await _pushNotificationService.ListRegistrationsAsync(); return Ok(); } /// /// Hilfsmethode die alle Walks so einstellt, dass wir nach dem Lauch kein Problem mit Wallets und Transaktionen haben /// /// public async Task PrepareWalksForLaunch() { //Publicwalk-Requests sollten kein Problem sein, da sie nur relevant sind, wenn Walks daraus erstellt wurden. //1. Alle Walks holen die "nur" angefragt wurden var walks = await _walkService.GetByStatusAsync(WalkStatus.Requested); foreach (var walk in walks) { //Walks die angefragt wurden, aber noch nicht gestartet sind, werden auf "Storniert" gesetzt walk.Status = WalkStatus.Cancelled; walk.CancelledBy = CancellationSource.GehGassi; walk.CancelledReason = "Prepare launch of gehgassi"; walk.UpdatedAt = DateTimeOffset.UtcNow; await _walkService.CommitAsync("System"); } //2. Alle Walks holen die "angenommen" wurden walks = await _walkService.GetByStatusAsync(WalkStatus.Accepted); foreach (var walk in walks) { walk.Status = WalkStatus.Cancelled; walk.CancelledBy = CancellationSource.GehGassi; walk.CancelledReason = "Prepare launch of gehgassi"; walk.UpdatedAt = DateTimeOffset.UtcNow; 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("System"); } //3. Alle Walks holen die "gestartet" wurden walks = await _walkService.GetByStatusAsync(WalkStatus.Started); foreach (var walk in walks) { walk.Status = WalkStatus.Completed; walk.Completed = DateTimeOffset.UtcNow; walk.UpdatedAt = DateTimeOffset.UtcNow; walk.CompletedInfo = string.Empty; walk.Defactation = true; await _walkService.CommitAsync(User.Identity.Name); //Rating erstellen var appUser = await _appUserService.GetAsync(walk.DogOwnerId); 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, 5, string.Empty); _ratingService.Add(rating); //Neu: Rating für jeden der Hunde erstellen wenn es mehrere sind, oder halt einen wenn nur einer ist var dogsList = JsonSerializer.Deserialize>(walk.DogsJson, new JsonSerializerOptions(JsonSerializerDefaults.Web)); foreach (var dogWalkJson in dogsList) { var ratingDog = _ratingService.Create(walk.DogWalkerId, appUser.Type, dogWalkJson.Id, RatingTarget.Dog, 5, string.Empty); _ratingService.Add(ratingDog); } await _ratingService.CommitAsync(User.Identity.Name); //Rating-Statistik für Hunde / Hunde aktualisieren foreach (var dogWalkJson in dogsList) { await _ratingService.UpdateRatingStatisticsAsync(dogWalkJson.Id, RatingTarget.Dog); } await _ratingService.CommitAsync(User.Identity.Name); } } //4. Alle Walks holen die "abgeschlossen" wurden walks = await _walkService.GetByStatusAsync(WalkStatus.Completed); foreach (var walk in walks) { walk.Status = WalkStatus.Confirmed; walk.Confirmed = DateTimeOffset.UtcNow; walk.UpdatedAt = DateTimeOffset.UtcNow; walk.PaymentStatus = PaymentStatus.Paid; await _walkService.CommitAsync(User.Identity.Name); //Zahlung veranlassen.... 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); } 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); } } } return Ok(); } /// /// Zurücksetzen der App User in Bezug auf Mangopay /// /// public async Task ResetAppUsers() { var appUsers = await _appUserService.GetAllAsync(); foreach (var appUser in appUsers) { appUser.PaymentId = string.Empty; appUser.KycPassed = false; appUser.KycPassedDate = null; appUser.BankId = string.Empty; appUser.Verified = false; appUser.VerifiedDate = null; appUser.AutoPayout = false; appUser.PaymentTermsAccepted = false; appUser.PaymentTermsAcceptedDate = null; appUser.NationalityCode = string.Empty; appUser.MainResidenceCode = string.Empty; appUser.UpdatedAt = DateTime.UtcNow; await _appUserService.CommitAsync("System"); } var wallets = await _walletService.GetAllAsync(); foreach (var wallet in wallets) { _walletService.Remove(wallet); } await _walletService.CommitAsync("System"); return Ok(); } /// /// Für alle App-User prüfen ob diese, wenn nötig einen Mangopay-User und Wallets haben /// /// 200 OK public async Task SetMangoPayAccounts() { var appUsers = await _appUserService.GetAllAsync(); foreach (var appUser in appUsers.Where(c => c.TermsAccepted && c.Address != null && !string.IsNullOrWhiteSpace(c.Address.CountryCode))) { System.Diagnostics.Debug.WriteLine($"Prüfe Benutzer: {appUser.FirstName} {appUser.LastName}"); if (!string.IsNullOrWhiteSpace(appUser.PaymentId) || appUser.Type == AppUserType.DogWalker || appUser.Type == AppUserType.Both) { if (string.IsNullOrWhiteSpace(appUser.PaymentId)) { System.Diagnostics.Debug.WriteLine($"{appUser.FirstName} {appUser.LastName} hat keinen MangoPay User"); //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)) appUser.MainResidenceCode = appUser.Address.CountryCode; if (!appUser.PaymentTermsAccepted || appUser.PaymentTermsAcceptedDate == null) { appUser.PaymentTermsAccepted = true; appUser.PaymentTermsAcceptedDate = DateTime.Now; } var createResult = await _mangoPayService.CreateOwnerAsync(appUser.Id, true); if (createResult.Success) { appUser.PaymentId = createResult.Value; appUser.UpdatedAt = DateTimeOffset.UtcNow; await _appUserService.CommitAsync("System"); System.Diagnostics.Debug.WriteLine($"{appUser.FirstName} {appUser.LastName} hat nun die MangoPayId: {appUser.PaymentId}"); //Wallets anlegen var walletFees = await _mangoPayService.CreateWalletAsync(appUser.Id, WalletType.Fees); 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) 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)) System.Diagnostics.Debug.WriteLine(createResult.ErrorMessage); if(createResult.ErrorMessages != null) foreach (var error in createResult.ErrorMessages) System.Diagnostics.Debug.WriteLine($"{error.Key} --> {error.Value}"); } } else { System.Diagnostics.Debug.WriteLine($"{appUser.FirstName} {appUser.LastName} hat einen MangoPay User mit der Id {appUser.PaymentId}"); //Es gibt einen MangoPay User. Das gilt nun für alle User. var hasChanges = false; if (string.IsNullOrWhiteSpace(appUser.NationalityCode)) { appUser.NationalityCode = appUser.Address.CountryCode; hasChanges = true; } if (string.IsNullOrEmpty(appUser.MainResidenceCode)) { appUser.MainResidenceCode = appUser.Address.CountryCode; hasChanges = true; } if (!appUser.PaymentTermsAccepted || appUser.PaymentTermsAcceptedDate == null) { appUser.PaymentTermsAccepted = true; appUser.PaymentTermsAcceptedDate = DateTime.Now; hasChanges = true; } if (hasChanges) { appUser.UpdatedAt = DateTimeOffset.UtcNow; await _appUserService.CommitAsync("System"); } //Hier nun Prüfen ob ein Benutzer bei Mangopay besteht. var hasOwnerResult = await _mangoPayService.OwnerExistsAsync(appUser.PaymentId); if (hasOwnerResult.Success) { if (hasOwnerResult.Value == false) { System.Diagnostics.Debug.WriteLine($"{appUser.FirstName} {appUser.LastName}: Die MangoPay-Id {appUser.PaymentId} existiert nicht bei MangoPay"); //Es gibt keinen User, also einen neuen anlegen und die neue Id speichern var createResult = await _mangoPayService.CreateOwnerAsync(appUser.Id, true); if (createResult.Success) { appUser.PaymentId = createResult.Value; appUser.UpdatedAt = DateTimeOffset.UtcNow; await _appUserService.CommitAsync("System"); System.Diagnostics.Debug.WriteLine($"{appUser.FirstName} {appUser.LastName} hat nun die MangoPayId: {appUser.PaymentId}"); } else { System.Diagnostics.Debug.WriteLine($"{appUser.FirstName} {appUser.LastName} konnte keine MangoPay ID bekommen"); } } else { System.Diagnostics.Debug.WriteLine($"{appUser.FirstName} {appUser.LastName}: Die MangoPay-Id {appUser.PaymentId} ist gültig!!!!"); } //Nun Wallets prüfen var wallets = await _walletService.GetAllAsync(appUser.Id); var creditWallet = wallets.FirstOrDefault(c => c.Type == WalletType.Credits); if (creditWallet == null) { //Wallet anlegen var walletCredits = await _mangoPayService.CreateWalletAsync(appUser.Id, WalletType.Credits); 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"); } else { //Prüfen ob Wallet existiert, sonst anlegen var walletExitsResult = await _mangoPayService.WalletExistsAsync(creditWallet.WalletId); if (walletExitsResult.Success && !walletExitsResult.Value) { System.Diagnostics.Debug.WriteLine($"{appUser.FirstName} {appUser.LastName}: Das Wallet mit der Id {creditWallet.WalletId} existiert nicht. Neues anlegen!"); var walletCredits = await _mangoPayService.CreateWalletAsync(appUser.Id, WalletType.Credits); if (walletCredits.Success) { _walletService.Remove(creditWallet); await _walletService.CommitAsync("System"); 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"); } } var feeWallet = wallets.FirstOrDefault(c => c.Type == WalletType.Fees); if (feeWallet == null) { //Wallet anlegen var walletFees = await _mangoPayService.CreateWalletAsync(appUser.Id, WalletType.Fees); if (walletFees.Success) System.Diagnostics.Debug.WriteLine($"{appUser.FirstName} {appUser.LastName}: Es wurde ein neues Fee-Wallet angelegt"); else System.Diagnostics.Debug.WriteLine($"{appUser.FirstName} {appUser.LastName}: Es konnte kein neues Fee-Wallet angelegt werde"); } else { //Prüfen ob Wallet existiert, sonst anlegen var walletExitsResult = await _mangoPayService.WalletExistsAsync(feeWallet.WalletId); if (walletExitsResult.Success && !walletExitsResult.Value) { System.Diagnostics.Debug.WriteLine($"{appUser.FirstName} {appUser.LastName}: Das Wallet mit der Id {feeWallet.WalletId} existiert nicht. Neues anlegen!"); var walletFees = await _mangoPayService.CreateWalletAsync(appUser.Id, WalletType.Fees); if (walletFees.Success) { _walletService.Remove(feeWallet); await _walletService.CommitAsync("System"); System.Diagnostics.Debug.WriteLine($"{appUser.FirstName} {appUser.LastName}: Es wurde ein neues Fees-Wallet angelegt"); } else System.Diagnostics.Debug.WriteLine($"{appUser.FirstName} {appUser.LastName}: Es konnte kein neues Fees-Wallet angelegt werde"); } } } } } else { System.Diagnostics.Debug.WriteLine($"Benutzer: {appUser.FirstName} {appUser.LastName} hat keine PaymentId und folgenden Typ: {appUser.Type}"); } } return Ok(); } /// /// Echtes Löschen von AppUsers die als gelöscht markiert sind /// /// public async Task RemoveDeletedAppUsers() { dynamic model = new ExpandoObject(); var ratingTargetsToUpdate = new List>(); var appUsers = await _appUserService.GetDeletedAsync(); model.AppUsersCount = appUsers.Count(); model.UsersCount = 0; model.FavouritesCount = 0; model.SystemMessageCount = 0; model.DeviceCount = 0; model.DeviceDeinstallationCount = 0; model.ConversationsCount = 0; model.RatingsCount = 0; foreach (var appUser in appUsers) { //Schritt 1: löschen der Dateien var postingPath = FileServiceHelper.GetAppUserPath(appUser.Id); await FileService.ClearDirectoryAsync(FileServiceHelper.DocumentContainer, postingPath); await RemoveThumbnail(FileServiceHelper.DocumentContainer, appUser.Photo, 400); await RemoveThumbnail(FileServiceHelper.DocumentContainer, appUser.Photo, 200); await RemoveThumbnail(FileServiceHelper.DocumentContainer, appUser.Photo, 100); //Schritt 2: Benutzer und Refreshtokens löschen var applicationUser = await _userService.GetByAppUserAsync(appUser.Id); if (applicationUser != null) { //Refreshtokens löschen await _refreshTokenService.RemoveAllAsync(applicationUser.Id, applicationUser.UserName); //Benutzer löschen _userService.Remove(applicationUser); model.UsersCount += 1; } //Schritt 3: Walker-Profil löschen await _appUserService.RemoveWalkerProfileAsync(appUser.Id); //Schritt 4: Blockierungen löschen await _appUserService.RemoveBlocksByBlockedUserAsync(appUser.Id); //Schritt 5: Ratings löschen var ratingTargets = await _ratingService.DeleteAllForAppUserAsync(appUser.Id); foreach (var ratingTarget in ratingTargets) { if (ratingTargetsToUpdate.FirstOrDefault(c => c.Item1 == ratingTarget.Item1 && c.Item2 == ratingTarget.Item2) == null) ratingTargetsToUpdate.Add(ratingTarget); } //Schritt 6: Favourites löschen var favouritesCount = await _favouriteService.DeleteAllForAppUserAsync(appUser.Id); model.FavouritesCount += favouritesCount; //Schritt 7: SystemMessages löschen var systemMessageCount = await _systemMessageService.DeleteAllForAppUserAsync(appUser.Id); model.SystemMessageCount += systemMessageCount; //Schritt 8: Devices vor löschen abmelden var devices = await _deviceService.GetAllAsync(appUser.Id); foreach (var device in devices) { model.DeviceCount += 1; #if RELEASE var success = await _pushNotificationService.DeleteInstallationByIdAsync(device.InstallationId); if(success) model.DeviceDeinstallationCount += 1; #endif await _deviceService.DeleteAsync(appUser.Id, device.InstallationId, true); } //Schritt 9: Konversationen löschen var conversations = await _messageService.RemoveConversationByAppUserAsync(appUser.Id); model.ConversationsCount += conversations; //AppReports löschen var appUserReportCount = await _appUserReportService.DeleteAllForAppUserAsync(appUser.Id); System.Diagnostics.Debug.WriteLine($"AppUserReports: {appUserReportCount}"); _appUserService.Remove(appUser); } model.RatingsCount = ratingTargetsToUpdate.Count; //Schritt 10: Löschen der gesamten Daten await _appUserService.CommitAsync(User.Identity.Name); //Schritt 11: Rating-Statistiken aktualisieren if (ratingTargetsToUpdate.Any()) { foreach (var ratingTargetToUpdate in ratingTargetsToUpdate) { await _ratingService.UpdateRatingStatisticsAsync(ratingTargetToUpdate.Item1, ratingTargetToUpdate.Item2); } await _ratingService.CommitAsync(User.Identity.Name); } return View(model); } } }