733 lines
33 KiB
C#
733 lines
33 KiB
C#
using System;
|
|
using System.Globalization;
|
|
using System.Linq;
|
|
using System.Threading;
|
|
using System.Threading.Tasks;
|
|
using gehGassi.Core.Interfaces;
|
|
using gehGassi.Core.Services;
|
|
using gehGassi.Domain.Common;
|
|
using gehGassi.Domain.Dogs;
|
|
using gehGassi.Domain.Messages;
|
|
using gehGassi.Dto.Messages;
|
|
using gehGassi.External.Services;
|
|
using gehGassi.Web.Helper;
|
|
using gehGassi.Web.Hubs;
|
|
using Microsoft.AspNetCore.Hosting;
|
|
using Microsoft.Extensions.Caching.Distributed;
|
|
using Microsoft.Extensions.DependencyInjection;
|
|
using Microsoft.Extensions.Hosting;
|
|
using Microsoft.Extensions.Logging;
|
|
using Microsoft.Extensions.Options;
|
|
using NetTopologySuite.Geometries;
|
|
using NetTopologySuite;
|
|
|
|
namespace gehGassi.Web.BackgroundServices
|
|
{
|
|
/// <summary>
|
|
/// Hintergrundservice der regelmäßige Aufgaben übernimmt
|
|
/// </summary>
|
|
public class BackgroundService : IHostedService, IDisposable
|
|
{
|
|
private Timer _timer;
|
|
private int _syncPoint = 0;
|
|
private readonly IServiceProvider _services;
|
|
private readonly ILogger<BackgroundService> _logger;
|
|
private readonly IOptions<BackgroundServiceOptions> _backgroundServiceOptions;
|
|
private readonly IDistributedCache _cache;
|
|
private readonly IServiceScopeFactory _resolver;
|
|
private readonly IWebHostEnvironment _webHostEnvironment;
|
|
|
|
/// <summary>
|
|
/// Erstellt eine Instanz
|
|
/// </summary>
|
|
/// <param name="services">Instanz eine IServiceProvider</param>
|
|
/// <param name="logger">Instanz eines ILogger</param>
|
|
/// <param name="backgroundServiceOptions">Instanz eines IOptions BackgroundServiceOptions</param>
|
|
/// <param name="cache">Instanz eines IDistributedCache</param>
|
|
/// <param name="resolver">Instanz eines IServiceScopeFactory</param>
|
|
/// <param name="webHostEnvironment">Instanz eines IWebHostEnvironment</param>
|
|
public BackgroundService(IServiceProvider services, ILogger<BackgroundService> logger, IOptions<BackgroundServiceOptions> backgroundServiceOptions, IDistributedCache cache, IServiceScopeFactory resolver,
|
|
IWebHostEnvironment webHostEnvironment)
|
|
{
|
|
_services = services;
|
|
_logger = logger;
|
|
_backgroundServiceOptions = backgroundServiceOptions;
|
|
_cache = cache;
|
|
_resolver = resolver;
|
|
_webHostEnvironment = webHostEnvironment;
|
|
}
|
|
|
|
/// <inheritdoc />
|
|
public Task StartAsync(CancellationToken cancellationToken)
|
|
{
|
|
_logger.LogInformation("BackgroundService started");
|
|
|
|
_timer = new Timer(async o => await DoWorkAsync(cancellationToken), null, TimeSpan.Zero, TimeSpan.FromSeconds(_backgroundServiceOptions.Value.TimerIntervalInSeconds));
|
|
|
|
return Task.CompletedTask;
|
|
}
|
|
|
|
/// <summary>
|
|
/// Task der die Abarbeitung übernimmt
|
|
/// </summary>
|
|
/// <param name="stoppingToken">CancellationToken</param>
|
|
/// <returns>Task</returns>
|
|
private async Task DoWorkAsync(CancellationToken stoppingToken)
|
|
{
|
|
//Achtung: in Azure muss in den Slots eine Variable "Slot" angelegt sein und in der Production-Slot muss diese auf "Production" stehen
|
|
var slotName = Environment.GetEnvironmentVariable("Slot");
|
|
var runTasks = true;
|
|
|
|
if (!string.IsNullOrWhiteSpace(slotName) && slotName.ToLower() != "production")
|
|
runTasks = false;
|
|
|
|
int sync = Interlocked.CompareExchange(ref _syncPoint, 1, 0);
|
|
|
|
if (sync == 0)
|
|
{
|
|
try
|
|
{
|
|
if (runTasks)
|
|
{
|
|
_timer.Change(Timeout.Infinite, Timeout.Infinite);
|
|
|
|
_logger.LogInformation("BackgroundService - Do Work");
|
|
|
|
await DeleteOldTempFilesAsync();
|
|
await RemoveExpiredRefreshTokensAsync();
|
|
await RemovePersistedTicketsAsync();
|
|
|
|
await InvalidateExpiredAppUserSubscription();
|
|
|
|
await ResetReservedListingsAsync();
|
|
await HandleKlarnaOrdersShipmentAsync();
|
|
await StartAndStopSpecialEntitiesAsync();
|
|
|
|
await AutoUnlockAppUsersAsync();
|
|
|
|
await CorrectInvalidAppUserLocationsAsync();
|
|
|
|
await TimeoutPublicWalkRequestsAsync();
|
|
|
|
await CancelTimedOutWalksAsync();
|
|
|
|
await CancelPendingWalksAsync();
|
|
|
|
if (_backgroundServiceOptions.Value.AutoComplete)
|
|
await CompleteWalksAsync();
|
|
|
|
if (_backgroundServiceOptions.Value.AutoConfirm)
|
|
{
|
|
await ConfirmCompletedWalksAsync();
|
|
await ConfirmCompletedWalksReminderAsync();
|
|
}
|
|
|
|
await SendSystemMessagesAsync();
|
|
|
|
await RemoveExpiredSystemMessagesAsync();
|
|
|
|
await RemoveExpiredBlocksAsync();
|
|
|
|
await RemoveExpiredMessagesAsync();
|
|
|
|
await SendPublicWalkRequestNotificationsAsync();
|
|
|
|
if (DateTimeOffset.UtcNow.DayOfWeek == DayOfWeek.Monday && DateTimeOffset.UtcNow.Hour == 3)
|
|
{
|
|
//Jeden Montag um 3 Uhr Auszahlungen durchführen
|
|
//Vorher noch prüfen ob diese bereits durchgeführt wurden
|
|
var lastPayout = await _cache.GetStringAsync("LastPayout");
|
|
if (lastPayout == null || string.IsNullOrWhiteSpace(lastPayout))
|
|
{
|
|
var options = new DistributedCacheEntryOptions();
|
|
options.SetAbsoluteExpiration(DateTimeOffset.UtcNow.AddHours(2));
|
|
await _cache.SetStringAsync("LastPayout", DateTimeOffset.UtcNow.ToString(), options);
|
|
|
|
//Jetzt Payout starten
|
|
_ = Task.Run(() => DoAutoPayoutAsync(_backgroundServiceOptions.Value.MinPayoutAmmount, _resolver));
|
|
}
|
|
}
|
|
|
|
|
|
_logger.LogInformation("BackgroundService - Do Work done");
|
|
}
|
|
|
|
}
|
|
catch (Exception ex)
|
|
{
|
|
_logger.LogError("BackgroundService Exception: {ex}", ex);
|
|
}
|
|
finally
|
|
{
|
|
_syncPoint = 0;
|
|
_timer.Change(TimeSpan.FromSeconds(_backgroundServiceOptions.Value.TimerIntervalInSeconds), TimeSpan.FromSeconds(_backgroundServiceOptions.Value.TimerIntervalInSeconds));
|
|
}
|
|
}
|
|
}
|
|
|
|
/// <summary>
|
|
/// Löschen alter Dateien im Temp-Ordner
|
|
/// </summary>
|
|
/// <returns>Task</returns>
|
|
private async Task DeleteOldTempFilesAsync()
|
|
{
|
|
using var scope = _services.CreateScope();
|
|
var fileService = scope.ServiceProvider.GetRequiredService<IFileService>();
|
|
await fileService.DeleteOldFilesAsync(FileServiceHelper.TempContainer, "", DateTimeOffset.UtcNow.AddMinutes(-60));
|
|
}
|
|
|
|
/// <summary>
|
|
/// Löschen abgelaufener Refreshtokens
|
|
/// </summary>
|
|
/// <returns></returns>
|
|
private async Task RemoveExpiredRefreshTokensAsync()
|
|
{
|
|
using var scope = _services.CreateScope();
|
|
var refreshTokenService = scope.ServiceProvider.GetRequiredService<IRefreshTokenService>();
|
|
await refreshTokenService.RemoveExpiredAsync("System");
|
|
await refreshTokenService.CommitAsync("System");
|
|
}
|
|
|
|
/// <summary>
|
|
/// Löschen abgelaufener PersistedTickets
|
|
/// </summary>
|
|
/// <returns></returns>
|
|
private async Task RemovePersistedTicketsAsync()
|
|
{
|
|
using var scope = _services.CreateScope();
|
|
var persistedTicketService = scope.ServiceProvider.GetRequiredService<IPersistedTicketService>();
|
|
await persistedTicketService.RemoveExpiredAsync();
|
|
await persistedTicketService.CommitAsync("System");
|
|
}
|
|
|
|
/// <summary>
|
|
/// Invalidierung abgelaufener AppUser-Abonnements
|
|
/// </summary>
|
|
/// <returns>Task</returns>
|
|
private async Task InvalidateExpiredAppUserSubscription()
|
|
{
|
|
using var scope = _services.CreateScope();
|
|
var subscriptionService = scope.ServiceProvider.GetRequiredService<ISubscriptionService>();
|
|
var count = await subscriptionService.InvalidateExipredAppUserSubscriptionsAsync(DateTimeOffset.UtcNow);
|
|
await subscriptionService.CommitAsync("System");
|
|
}
|
|
|
|
/// <inheritdoc />
|
|
public Task StopAsync(CancellationToken cancellationToken)
|
|
{
|
|
_logger.LogInformation("BackgroundService stopped");
|
|
_timer?.Change(Timeout.Infinite, 0);
|
|
return Task.CompletedTask;
|
|
}
|
|
|
|
#region Tasks die dann in Webjobs ausgelagert werden sollten
|
|
|
|
//1. Reservierung für Listungen
|
|
|
|
/// <summary>
|
|
/// Zurücksetzen von reservierten Listungen wenn keine Zahlung erfolgt ist
|
|
/// </summary>
|
|
/// <returns>Task</returns>
|
|
private async Task ResetReservedListingsAsync()
|
|
{
|
|
using var scope = _services.CreateScope();
|
|
var listingService = scope.ServiceProvider.GetRequiredService<IListingService>();
|
|
await listingService.ResetReservedAsync(DateTimeOffset.UtcNow);
|
|
await listingService.CommitAsync("System");
|
|
}
|
|
|
|
//2. Klarna-Versand wenn nur digitale Produkte
|
|
//Besteht aus 2 Teilen - setzen der Bestellungen welche nur digitale Produkte beinhalten auf "Shipped"
|
|
//Dann noch für alle Bestellungen die "Shipped" wurden das an Klarna melden
|
|
|
|
/// <summary>
|
|
/// Klarna-Versand wenn nur digitale Produkte
|
|
/// </summary>
|
|
/// <returns>Task</returns>
|
|
private async Task HandleKlarnaOrdersShipmentAsync()
|
|
{
|
|
using var scope = _services.CreateScope();
|
|
var orderService = scope.ServiceProvider.GetRequiredService<IOrderService>();
|
|
|
|
await orderService.SetShipmentForKlarnaDigitalOnlyAsync();
|
|
await orderService.CommitAsync("System");
|
|
|
|
var orders = await orderService.GetOrdersKlarnaToShipAsync();
|
|
if (orders.Any())
|
|
{
|
|
try
|
|
{
|
|
var klarnaService = scope.ServiceProvider.GetRequiredService<IKlarnaService>();
|
|
var shopSettingsService = scope.ServiceProvider.GetRequiredService<IShopSettingsService>();
|
|
var shopSettings = await shopSettingsService.GetAsync();
|
|
|
|
int ordersHandled = 0;
|
|
|
|
foreach (var order in orders)
|
|
{
|
|
if (order.KlarnaShipmentError)
|
|
continue;
|
|
|
|
var result = await klarnaService.CaptureOrderAsync(order.Id, shopSettings.KlarnaClientId, shopSettings.KlarnaSecret);
|
|
switch (result)
|
|
{
|
|
case CaptureOrderResult.Success:
|
|
order.KlarnaShipmentSentDate = DateTime.UtcNow;
|
|
order.PaymentInfo = $"{DateTime.UtcNow.ToString()} Shipment success" + Environment.NewLine + order.PaymentInfo;
|
|
break;
|
|
case CaptureOrderResult.CaptureNotAllowed:
|
|
order.KlarnaShipmentError = true;
|
|
order.PaymentInfo = $"{DateTime.UtcNow.ToString()} Error: Capture not allowed" + Environment.NewLine + order.PaymentInfo;
|
|
break;
|
|
case CaptureOrderResult.RemainingAuthorizedAmount:
|
|
order.KlarnaShipmentError = true;
|
|
order.PaymentInfo = $"{DateTime.UtcNow.ToString()} Error: RemainingAuthorizedAmount 0" + Environment.NewLine + order.PaymentInfo;
|
|
break;
|
|
case CaptureOrderResult.OrderNotFound:
|
|
order.KlarnaShipmentError = true;
|
|
order.PaymentInfo = $"{DateTime.UtcNow.ToString()} Error: Order not found" + Environment.NewLine + order.PaymentInfo;
|
|
break;
|
|
case CaptureOrderResult.Timeout:
|
|
//Nichts tun, soll nochmal probiert werden
|
|
order.PaymentInfo = $"{DateTime.UtcNow.ToString()} Error: Timeout" + Environment.NewLine + order.PaymentInfo;
|
|
break;
|
|
case CaptureOrderResult.AuthorizationFailed:
|
|
//Nichts tun, soll nochmal probiert werden
|
|
order.PaymentInfo = $"{DateTime.UtcNow.ToString()} Error: Authorization failed" + Environment.NewLine + order.PaymentInfo;
|
|
break;
|
|
//Auth failed
|
|
default:
|
|
//Nichts tun, soll nochmal probiert werden
|
|
order.PaymentInfo = $"{DateTime.UtcNow.ToString()} Error: Unknown Error" + Environment.NewLine + order.PaymentInfo;
|
|
break;
|
|
}
|
|
}
|
|
|
|
await orderService.CommitAsync("klarna shipment service");
|
|
}
|
|
catch{}
|
|
}
|
|
}
|
|
|
|
|
|
//3. Starten und Stoppen von Listungen, Werbungen, Bannern, News und Gutscheinkampagnen und Pins nach Datum
|
|
|
|
/// <summary>
|
|
/// Starten und Stoppen von Listungen, Werbungen, Bannern und Pins nach Datum
|
|
/// </summary>
|
|
/// <returns>Task</returns>
|
|
private async Task StartAndStopSpecialEntitiesAsync()
|
|
{
|
|
using var scope = _services.CreateScope();
|
|
var listingService = scope.ServiceProvider.GetRequiredService<IListingService>();
|
|
var advertisementService = scope.ServiceProvider.GetRequiredService<IAdvertisementService>();
|
|
var bannerService = scope.ServiceProvider.GetRequiredService<IBannerService>();
|
|
var pinService = scope.ServiceProvider.GetRequiredService<IPinService>();
|
|
var newsService = scope.ServiceProvider.GetRequiredService<INewsService>();
|
|
var voucherCampaignService = scope.ServiceProvider.GetRequiredService<IVoucherCampaignService>();
|
|
|
|
await listingService.StartBookedAsnyc();
|
|
await listingService.StopRunningAsync();
|
|
await listingService.CommitAsync("System");
|
|
|
|
await advertisementService.StartBookedAsnyc();
|
|
await advertisementService.StopRunningAsync();
|
|
await advertisementService.CommitAsync("System");
|
|
|
|
await bannerService.StartBookedAsnyc();
|
|
await bannerService.StopRunningAsync();
|
|
await bannerService.CommitAsync("System");
|
|
|
|
await pinService.StartBookedAsnyc();
|
|
await pinService.StopRunningAsync();
|
|
await pinService.CommitAsync("System");
|
|
|
|
await newsService.StartApprovedAsnyc();
|
|
await newsService.StopRunningAsync();
|
|
await newsService.CommitAsync("System");
|
|
|
|
await voucherCampaignService.StartBookedAsnyc();
|
|
await voucherCampaignService.StopRunningAsync();
|
|
await voucherCampaignService.CommitAsync("System");
|
|
}
|
|
|
|
//4. Clear (das sind Log-Dateien hier konkret Audits die älter als z.B. ein Jahr sind
|
|
|
|
//5. Auto-Entsperren von App-Usern
|
|
|
|
/// <summary>
|
|
/// Automatisches Entsperren von App-Usern deren Sperrdatum erreicht wurde
|
|
/// </summary>
|
|
/// <returns>Task</returns>
|
|
private async Task AutoUnlockAppUsersAsync()
|
|
{
|
|
using var scope = _services.CreateScope();
|
|
var appUserService = scope.ServiceProvider.GetRequiredService<IAppUserService>();
|
|
|
|
await appUserService.AutoUnlockAsync();
|
|
await appUserService.CommitAsync("System");
|
|
|
|
}
|
|
|
|
/// <summary>
|
|
/// Bei AppUsern deren Location nicht korrekt eingetragen wurde, diese korrigieren wenn möglich
|
|
/// </summary>
|
|
/// <returns>Task</returns>
|
|
private async Task CorrectInvalidAppUserLocationsAsync()
|
|
{
|
|
using var scope = _services.CreateScope();
|
|
var appUserService = scope.ServiceProvider.GetRequiredService<IAppUserService>();
|
|
var geoLocationService = scope.ServiceProvider.GetRequiredService<IGeoLocationService>();
|
|
|
|
var appUsers = await appUserService.GetWithInvalidLocationAsync();
|
|
if (appUsers.Any())
|
|
{
|
|
foreach (var appUser in appUsers)
|
|
{
|
|
var location = await geoLocationService.GetLocationAsync(appUser.Address, 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;
|
|
appUser.UpdatedAt = DateTimeOffset.UtcNow;
|
|
}
|
|
}
|
|
|
|
await appUserService.CommitAsync("System");
|
|
}
|
|
}
|
|
|
|
/// <summary>
|
|
/// Timeout von abgelaufenen öffentlichen Anfragen setzen
|
|
/// </summary>
|
|
/// <returns>Task</returns>
|
|
private async Task TimeoutPublicWalkRequestsAsync()
|
|
{
|
|
using var scope = _services.CreateScope();
|
|
var publicWalkRequestService = scope.ServiceProvider.GetRequiredService<IPublicWalkRequestService>();
|
|
|
|
await publicWalkRequestService.SetTimedOutAsync(DateTimeOffset.UtcNow);
|
|
await publicWalkRequestService.CommitAsync("System");
|
|
|
|
}
|
|
|
|
/// <summary>
|
|
/// Abgelaufene Walks stornieren.
|
|
/// Diese sind im Status "Request" und das Startdatum wurde bereits erreicht
|
|
/// </summary>
|
|
/// <returns>Task</returns>
|
|
private async Task CancelTimedOutWalksAsync()
|
|
{
|
|
using var scope = _services.CreateScope();
|
|
var walkService = scope.ServiceProvider.GetRequiredService<IWalkService>();
|
|
|
|
await walkService.CancelTimedOutAsync(DateTimeOffset.UtcNow);
|
|
await walkService.CommitAsync("System");
|
|
}
|
|
|
|
/// <summary>
|
|
/// Walks stornieren die direkt gebucht wurden und nach X Minuten nicht bezahlt wurden
|
|
/// </summary>
|
|
/// <returns>Task</returns>
|
|
private async Task CancelPendingWalksAsync()
|
|
{
|
|
using var scope = _services.CreateScope();
|
|
var walkService = scope.ServiceProvider.GetRequiredService<IWalkService>();
|
|
|
|
await walkService.CancelPendingAsync(DateTimeOffset.UtcNow, _backgroundServiceOptions.Value.CancelPendingMinutes);
|
|
await walkService.CommitAsync("System");
|
|
}
|
|
|
|
/// <summary>
|
|
/// Walks abschliessen, welche nicht innerhalb von X Minuten abgeschlossen wurden
|
|
/// </summary>
|
|
/// <returns>Task</returns>
|
|
private async Task CompleteWalksAsync()
|
|
{
|
|
using var scope = _services.CreateScope();
|
|
var walkService = scope.ServiceProvider.GetRequiredService<IWalkService>();
|
|
|
|
await walkService.CompleteAutoAsync(DateTimeOffset.UtcNow, _backgroundServiceOptions.Value.CompleteMinutes);
|
|
await walkService.CommitAsync("System");
|
|
}
|
|
|
|
/// <summary>
|
|
/// Walks bestätigen die abgeschlossen, aber innerhalb von X Minuten nicht bestätigt wurden
|
|
/// </summary>
|
|
/// <returns>Task</returns>
|
|
private async Task ConfirmCompletedWalksAsync()
|
|
{
|
|
using var scope = _services.CreateScope();
|
|
var walkService = scope.ServiceProvider.GetRequiredService<IWalkService>();
|
|
|
|
await walkService.ConfirmCompletedAsync(DateTimeOffset.UtcNow, _backgroundServiceOptions.Value.ConfirmationMinutes);
|
|
await walkService.CommitAsync("System");
|
|
}
|
|
|
|
/// <summary>
|
|
/// Walks bestätigen die abgeschlossen Erinnerung senden
|
|
/// </summary>
|
|
/// <returns>Task</returns>
|
|
private async Task ConfirmCompletedWalksReminderAsync()
|
|
{
|
|
using var scope = _services.CreateScope();
|
|
var walkService = scope.ServiceProvider.GetRequiredService<IWalkService>();
|
|
|
|
await walkService.ConfirmCompletedReminderAsync(DateTimeOffset.UtcNow, _backgroundServiceOptions.Value.ConfirmationReminderMinutes);
|
|
await walkService.CommitAsync("System");
|
|
}
|
|
|
|
/// <summary>
|
|
/// Löschen abgelaufener Systemnachrichten
|
|
/// </summary>
|
|
/// <returns></returns>
|
|
private async Task RemoveExpiredSystemMessagesAsync()
|
|
{
|
|
using var scope = _services.CreateScope();
|
|
var systemMessageService = scope.ServiceProvider.GetRequiredService<ISystemMessageService>();
|
|
|
|
await systemMessageService.RemoveExpiredAsync(DateTimeOffset.UtcNow);
|
|
await systemMessageService.CommitAsync("System");
|
|
}
|
|
|
|
/// <summary>
|
|
/// Löschen abgelaufener Blockierungen
|
|
/// </summary>
|
|
/// <returns></returns>
|
|
private async Task RemoveExpiredBlocksAsync()
|
|
{
|
|
using var scope = _services.CreateScope();
|
|
var applicationUserService = scope.ServiceProvider.GetRequiredService<IAppUserService>();
|
|
|
|
await applicationUserService.RemoveExpiredBlocksAsync(DateTimeOffset.UtcNow);
|
|
await applicationUserService.CommitAsync("System");
|
|
}
|
|
|
|
/// <summary>
|
|
/// Löschen von Nachrichten die nicht abgehlot wurden
|
|
/// </summary>
|
|
/// <returns></returns>
|
|
private async Task RemoveExpiredMessagesAsync()
|
|
{
|
|
using var scope = _services.CreateScope();
|
|
var messageService = scope.ServiceProvider.GetRequiredService<IMessageService>();
|
|
|
|
var removedCount = await messageService.RemoveUnreadMessagesAsync(DateTimeOffset.UtcNow.AddMonths(-1));
|
|
if(removedCount > 0)
|
|
await messageService.CommitAsync("System");
|
|
|
|
removedCount = await messageService.RemoveMessageCopiesAsync(DateTimeOffset.UtcNow.AddDays(-7));
|
|
if (removedCount > 0)
|
|
await messageService.CommitAsync("System");
|
|
}
|
|
|
|
/// <summary>
|
|
/// Senden von Systemnachtichten die gesendet werden sollen
|
|
/// </summary>
|
|
/// <returns>Task</returns>
|
|
private async Task SendSystemMessagesAsync()
|
|
{
|
|
using var scope = _services.CreateScope();
|
|
var systemMessageService = scope.ServiceProvider.GetRequiredService<ISystemMessageService>();
|
|
var appUserService = scope.ServiceProvider.GetRequiredService<IAppUserService>();
|
|
var pushNotificationService = scope.ServiceProvider.GetRequiredService<IPushNotificationService>();
|
|
|
|
var messagesToSend = await systemMessageService.GetToSendAsync(DateTimeOffset.UtcNow);
|
|
if (messagesToSend != null && messagesToSend.Any())
|
|
{
|
|
foreach (var message in messagesToSend)
|
|
{
|
|
message.AppUserCount = await appUserService.CountForSystemMessageAsync(new SystemMessageAppUserQuery() { AppUserType = message.AppUserType, City = message.City, Country = message.Country, Sex = message.Sex, State = message.State, VerifiedOnly = message.VerifiedOnly, Zip = message.Zip });
|
|
message.SentCount = message.AppUserCount;
|
|
message.HasBeenSent = true;
|
|
message.SentDate = DateTimeOffset.UtcNow;
|
|
message.SentBy = "System";
|
|
await systemMessageService.CommitAsync("System");
|
|
|
|
var appUsers = await appUserService.GetForSystemMessageAsync(new SystemMessageAppUserQuery() {AppUserType = message.AppUserType, City = message.City, Country = message.Country, Sex = message.Sex, State = message.State, VerifiedOnly = message.VerifiedOnly, Zip = message.Zip });
|
|
var sentCount = 0;
|
|
foreach (var appUser in appUsers)
|
|
{
|
|
sentCount += 1;
|
|
systemMessageService.Add(appUser.Id, appUser.Type, message.Id.ToString(), DateTimeOffset.UtcNow.AddDays(14), message.Message);
|
|
if (message.SendPushNotification)
|
|
{
|
|
await pushNotificationService.SendNewTextMessageAsync(appUser.Id, message.Id.ToString());
|
|
}
|
|
}
|
|
|
|
if (sentCount > 0)
|
|
{
|
|
await systemMessageService.CommitAsync("System");
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
/// <summary>
|
|
/// Senden von Benachrichtigungen wenn eine öffentliche Anfrage erstellt wurde und Walker in der Nähe benachrichtigt werden sollen
|
|
/// </summary>
|
|
/// <returns>Task</returns>
|
|
private async Task SendPublicWalkRequestNotificationsAsync()
|
|
{
|
|
using var scope = _services.CreateScope();
|
|
var publicWalkRequestService = scope.ServiceProvider.GetRequiredService<IPublicWalkRequestService>();
|
|
var pushNotificationService = scope.ServiceProvider.GetRequiredService<IPushNotificationService>();
|
|
var appUserService = scope.ServiceProvider.GetRequiredService<IAppUserService>();
|
|
|
|
var notificationsToSend = await publicWalkRequestService.GetNotificationsToSendAsync();
|
|
if (notificationsToSend != null && notificationsToSend.Any())
|
|
{
|
|
foreach (var notification in notificationsToSend)
|
|
{
|
|
var walkers = await appUserService.GetWalkersForNotificationAsync(notification.DogOwnerId, notification.Location);
|
|
int sentCount = 0;
|
|
if (walkers != null && walkers.Any())
|
|
sentCount = walkers.Count;
|
|
|
|
notification.HasBeenSent = true;
|
|
notification.SentCount = sentCount;
|
|
notification.SentDate = DateTimeOffset.UtcNow;
|
|
await publicWalkRequestService.CommitAsync("System");
|
|
|
|
//Senden wenn geht
|
|
if (walkers != null && walkers.Any())
|
|
{
|
|
foreach (var walker in walkers)
|
|
{
|
|
await pushNotificationService.SendPublicWalkRequestAvailableAsync(walker.Id, notification.PublicWalkRequestId);
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
#endregion
|
|
|
|
#region Payout
|
|
|
|
/// <summary>
|
|
/// Task der für alle App-User eine Autoauszahlung durchführt, sofern der Benutzer dies aktiviert hat
|
|
/// </summary>
|
|
/// <param name="minPayoutAmmount">Mindestbetrag für Auszahlung</param>
|
|
/// <param name="resolver">IServiceScopeFactory</param>
|
|
/// <returns>Task</returns>
|
|
private async Task DoAutoPayoutAsync(long minPayoutAmmount, IServiceScopeFactory resolver)
|
|
{
|
|
try
|
|
{
|
|
using var scope = resolver.CreateScope();
|
|
var svcProvider = scope.ServiceProvider;
|
|
|
|
var appUserService = svcProvider.GetRequiredService<IAppUserService>();
|
|
var walletService = svcProvider.GetRequiredService<IWalletService>();
|
|
var mangoPayService = svcProvider.GetRequiredService<IMangoPayService>();
|
|
var payoutService = svcProvider.GetRequiredService<IPayoutService>();
|
|
var systemMessageService = svcProvider.GetRequiredService<ISystemMessageService>();
|
|
var appHubSender = svcProvider.GetRequiredService<IAppHubSender>();
|
|
var pushnotificationService = svcProvider.GetRequiredService<IPushNotificationService>();
|
|
|
|
if (appUserService != null && walletService != null && mangoPayService != null && payoutService != null && pushnotificationService != null)
|
|
{
|
|
var appUsers = await appUserService.GetForAutoPayoutAsync();
|
|
if (appUsers != null && appUsers.Any())
|
|
{
|
|
foreach (var appUser in appUsers)
|
|
{
|
|
if(appUser.Locked)
|
|
continue;
|
|
try
|
|
{
|
|
var creditWallet = await walletService.GetAsync(appUser.Id, WalletType.Credits);
|
|
if (creditWallet != null)
|
|
{
|
|
if (creditWallet.Balance >= minPayoutAmmount)
|
|
{
|
|
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);
|
|
}
|
|
|
|
var ammount = creditWallet.Balance;
|
|
|
|
var payout = payoutService.Create(appUser.Id, appUser.PaymentId, "", creditWallet.Id, creditWallet.WalletId, appUser.BankId, iban, bic, ammount, "EUR");
|
|
var payoutResult = await mangoPayService.CreatePayoutAsync(appUser.PaymentId, creditWallet.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("System");
|
|
|
|
//Wallet aktualisieren
|
|
await mangoPayService.GetWalletBalanceAsync(appUser.Id, WalletType.Credits);
|
|
|
|
//Benachrichtigung
|
|
if (systemMessageService != null && appHubSender != null)
|
|
{
|
|
if (appUser.Type == AppUserType.DogOwner || appUser.Type == AppUserType.Both)
|
|
{
|
|
systemMessageService.Add(appUser.Id, AppUserType.DogOwner, payout.Id, SystemMessageTables.Payout, SystemMessageType.PayoutUpdate, DateTimeOffset.UtcNow.AddDays(14));
|
|
await systemMessageService.CommitAsync("System");
|
|
await appHubSender.SystemMessageAddedAsync(appUser.Id);
|
|
await pushnotificationService.SendPayoutUpdateAsync(appUser.Id, payout.Id);
|
|
}
|
|
else if (appUser.Type == AppUserType.DogWalker || appUser.Type == AppUserType.Both)
|
|
{
|
|
systemMessageService.Add(appUser.Id, AppUserType.DogWalker, payout.Id, SystemMessageTables.Payout, SystemMessageType.PayoutUpdate, DateTimeOffset.UtcNow.AddDays(14));
|
|
await systemMessageService.CommitAsync("System");
|
|
await appHubSender.SystemMessageAddedAsync(appUser.Id);
|
|
await pushnotificationService.SendPayoutUpdateAsync(appUser.Id, payout.Id);
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
catch (Exception ex)
|
|
{
|
|
System.Diagnostics.Debug.WriteLine(ex.Message);
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
catch (Exception ex)
|
|
{
|
|
System.Diagnostics.Debug.WriteLine(ex.Message);
|
|
}
|
|
}
|
|
|
|
#endregion
|
|
|
|
/// <inheritdoc />
|
|
public void Dispose()
|
|
{
|
|
_timer?.Dispose();
|
|
}
|
|
}
|
|
}
|