236 lines
10 KiB
C#
236 lines
10 KiB
C#
using gehGassi.Core.Interfaces;
|
|
using gehGassi.Domain.Pages;
|
|
using System;
|
|
using System.Collections.Generic;
|
|
using System.Linq;
|
|
using System.Text;
|
|
using System.Threading.Tasks;
|
|
using gehGassi.Domain.Coins;
|
|
using gehGassi.Domain.Common;
|
|
using gehGassi.Domain.Walks;
|
|
using Microsoft.EntityFrameworkCore;
|
|
|
|
namespace gehGassi.Core.Services
|
|
{
|
|
/// <summary>
|
|
/// Service der die Verwaltung von Coin-Konten, Transaktionen und Monats- und Jahresstatistiken realisiert
|
|
/// </summary>
|
|
public class CoinsService : ServiceBase<CoinsAccount>, ICoinsService
|
|
{
|
|
private readonly IRepository<CoinsTransaction> _transactionRepository;
|
|
private readonly IRepository<CoinsPerMonth> _perMonthRepository;
|
|
private readonly IRepository<CoinsPerMonthWithNames> _perMonthNamesRepository;
|
|
private readonly IRepository<CoinsPerYear> _perYearRepository;
|
|
private readonly IRepository<CoinsPerYearWithNames> _perYearNamesRepository;
|
|
|
|
/// <summary>
|
|
/// Erstellt eine Instanz
|
|
/// </summary>
|
|
/// <param name="unitOfWork">Instanz eines IUnitOfWork</param>
|
|
public CoinsService(IUnitOfWork unitOfWork) : base(unitOfWork)
|
|
{
|
|
_transactionRepository = unitOfWork.GetRepository<CoinsTransaction>();
|
|
_perMonthRepository = unitOfWork.GetRepository<CoinsPerMonth>();
|
|
_perMonthNamesRepository = unitOfWork.GetRepository<CoinsPerMonthWithNames>();
|
|
_perYearRepository = unitOfWork.GetRepository<CoinsPerYear>();
|
|
_perYearNamesRepository = unitOfWork.GetRepository<CoinsPerYearWithNames>();
|
|
}
|
|
|
|
/// <summary>
|
|
/// Gibt einen Coin-Account zurück oder erstellt einen neuen wenn noch nicht vorhanden
|
|
/// </summary>
|
|
/// <param name="appUserId">Id des AppUsers</param>
|
|
/// <param name="appUserType">Typ des AppUsers</param>
|
|
/// <returns>CoinAccount</returns>
|
|
public async Task<CoinsAccount> GetOrCreateAsync(string appUserId, AppUserType appUserType)
|
|
{
|
|
var account = await Repository.FirstOrDefaultAsync(c => c.AppUserId == appUserId && c.AppUserType == appUserType);
|
|
|
|
if (account == null)
|
|
{
|
|
account = new CoinsAccount()
|
|
{
|
|
Id = Guid.NewGuid().ToString("N"),
|
|
AppUserId = appUserId,
|
|
AppUserType = appUserType,
|
|
Balance = 0,
|
|
Created = DateTimeOffset.UtcNow,
|
|
UpdatedAt = DateTimeOffset.UtcNow
|
|
};
|
|
Repository.Add(account);
|
|
await CommitAsync("System");
|
|
}
|
|
|
|
return account;
|
|
}
|
|
|
|
/// <summary>
|
|
/// Einzahlen einer Coins-Summe auf das passende Konto eines AppUsers
|
|
/// </summary>
|
|
/// <param name="appUserId">Id des AppUsers</param>
|
|
/// <param name="appUserType">Typ des AppUsers</param>
|
|
/// <param name="ammount">Coins-Betrag der eingezahlt werden soll</param>
|
|
/// <param name="walkId">Optional: Id des Walks auf den sich die Transaktion bezieht</param>
|
|
/// <returns>Transaktion</returns>
|
|
public async Task<CoinsTransaction> DepositAsync(string appUserId, AppUserType appUserType, decimal ammount, string walkId)
|
|
{
|
|
var account = await GetOrCreateAsync(appUserId, appUserType);
|
|
|
|
//Transaktion anlegen
|
|
var transaction = new CoinsTransaction()
|
|
{
|
|
TransactionType = CoinsTransactionType.Deposit,
|
|
AccountId = account.Id,
|
|
Ammount = ammount,
|
|
WalkId = walkId,
|
|
Created = DateTimeOffset.UtcNow
|
|
};
|
|
_transactionRepository.Add(transaction);
|
|
|
|
account.Balance += ammount;
|
|
|
|
//Punkte für das Monatskonto
|
|
var coinsPerMonth = await GetOrCreateCoinsPerMonthAsync(appUserId, appUserType, DateTimeOffset.UtcNow);
|
|
coinsPerMonth.Balance += ammount;
|
|
coinsPerMonth.LastUpdate = DateTimeOffset.UtcNow;
|
|
|
|
//Punkte für das Jahreskonto
|
|
var coinsPerYear = await GetOrCreateCoinsPerYearAsync(appUserId, appUserType, DateTimeOffset.UtcNow);
|
|
coinsPerYear.Balance += ammount;
|
|
coinsPerYear.LastUpdate = DateTimeOffset.UtcNow;
|
|
|
|
await CommitAsync("System");
|
|
|
|
return transaction;
|
|
}
|
|
|
|
/// <summary>
|
|
/// Abbuchen einer Coins-Summe von dem passenden Konto eines AppUsers
|
|
/// </summary>
|
|
/// <param name="appUserId">Id des AppUsers</param>
|
|
/// <param name="appUserType">Typ des AppUsers</param>
|
|
/// <param name="ammount">Coins-Betrag der eingezahlt werden soll</param>
|
|
/// <returns>CoinsTransaction</returns>
|
|
public async Task<CoinsTransaction> WithdrawAsync(string appUserId, AppUserType appUserType, decimal ammount)
|
|
{
|
|
var account = await GetOrCreateAsync(appUserId, appUserType);
|
|
|
|
if (account.Balance < ammount)
|
|
return null;
|
|
|
|
//Transaktion anlegen
|
|
var transaction = new CoinsTransaction()
|
|
{
|
|
TransactionType = CoinsTransactionType.Withdrawal,
|
|
AccountId = account.Id,
|
|
Ammount = ammount,
|
|
WalkId = string.Empty,
|
|
Created = DateTimeOffset.UtcNow
|
|
};
|
|
_transactionRepository.Add(transaction);
|
|
|
|
account.Balance -= ammount;
|
|
|
|
await CommitAsync("System");
|
|
|
|
return transaction;
|
|
}
|
|
|
|
/// <summary>
|
|
/// Gibt den Coins-Stand eines AppUsers für einen Monat zurück
|
|
/// </summary>
|
|
/// <param name="appUserId">Id des AppUsers</param>
|
|
/// <param name="appUserType">Typ des AppUsers</param>
|
|
/// <param name="date">Datum</param>
|
|
/// <returns>CoinsPerMonth</returns>
|
|
public async Task<CoinsPerMonth> GetOrCreateCoinsPerMonthAsync(string appUserId, AppUserType appUserType, DateTimeOffset date)
|
|
{
|
|
var coinsPerMonth = await _perMonthRepository.FirstOrDefaultAsync(c => c.AppUserId == appUserId && c.AppUserType == appUserType && c.Year == date.Year && c.Month == date.Month);
|
|
|
|
if (coinsPerMonth == null)
|
|
{
|
|
coinsPerMonth = new CoinsPerMonth()
|
|
{
|
|
AppUserId = appUserId,
|
|
AppUserType = appUserType,
|
|
Year = date.Year,
|
|
Month = date.Month,
|
|
Balance = 0,
|
|
LastUpdate = DateTimeOffset.UtcNow
|
|
};
|
|
//Keine Wertung rückwirkend erstellen
|
|
if (date.Year == DateTimeOffset.UtcNow.Year && date.Month == DateTimeOffset.UtcNow.Month)
|
|
{
|
|
_perMonthRepository.Add(coinsPerMonth);
|
|
await CommitAsync("System");
|
|
}
|
|
}
|
|
|
|
return coinsPerMonth;
|
|
}
|
|
|
|
/// <summary>
|
|
/// Gibt den Coins-Stand eines AppUsers für ein Jahr zurück
|
|
/// </summary>
|
|
/// <param name="appUserId">Id des AppUsers</param>
|
|
/// <param name="appUserType">Typ des AppUsers</param>
|
|
/// <param name="date">Datum</param>
|
|
/// <returns>CoinsPerYear</returns>
|
|
public async Task<CoinsPerYear> GetOrCreateCoinsPerYearAsync(string appUserId, AppUserType appUserType, DateTimeOffset date)
|
|
{
|
|
var coinsPerYear = await _perYearRepository.FirstOrDefaultAsync(c => c.AppUserId == appUserId && c.AppUserType == appUserType && c.Year == date.Year);
|
|
|
|
if (coinsPerYear == null)
|
|
{
|
|
coinsPerYear = new CoinsPerYear()
|
|
{
|
|
AppUserId = appUserId,
|
|
AppUserType = appUserType,
|
|
Year = date.Year,
|
|
Balance = 0,
|
|
LastUpdate = DateTimeOffset.UtcNow
|
|
};
|
|
//Keine Wertung rückwirkend erstellen
|
|
if (date.Year == DateTimeOffset.UtcNow.Year)
|
|
{
|
|
_perYearRepository.Add(coinsPerYear);
|
|
await CommitAsync("System");
|
|
}
|
|
}
|
|
|
|
return coinsPerYear;
|
|
}
|
|
|
|
/// <summary>
|
|
/// Gibt die Top X der Coins je Monat für ein Jahr und Monat zurück.
|
|
/// Sortiert nach Coins absteigend und bei Gleichstand nach LastUpdate aufsteigend
|
|
/// </summary>
|
|
/// <param name="count">Anzalh Datensätze</param>
|
|
/// <param name="appUserType">Typ des AppUsers</param>
|
|
/// <param name="year">Jahr</param>
|
|
/// <param name="month">Monat</param>
|
|
/// <param name="minBalance">Mindest-Wert der erreicht werden musste</param>
|
|
/// <returns>Liste CoinsPerMonthWithNames</returns>
|
|
public async Task<List<CoinsPerMonthWithNames>> GetMonthlyTopAsync(int count, AppUserType appUserType, int year, int month, decimal minBalance)
|
|
{
|
|
var coins = await _perMonthNamesRepository.QueryView(c => c.AppUserType == appUserType && c.Year == year && c.Month == month && c.Balance >= minBalance).OrderByDescending(c => c.Balance).ThenBy(c => c.LastUpdate).Take(count).ToListAsync();
|
|
return coins;
|
|
}
|
|
|
|
/// <summary>
|
|
/// Gibt die Top X der Coins je Jahr zurück.
|
|
/// Sortiert nach Coins absteigend und bei Gleichstand nach LastUpdate aufsteigend
|
|
/// </summary>
|
|
/// <param name="count">Anzalh Datensätze</param>
|
|
/// <param name="appUserType">Typ des AppUsers</param>
|
|
/// <param name="year">Jahr</param>
|
|
/// <param name="minBalance">Mindest-Wert der erreicht werden musste</param>
|
|
/// <returns>Liste CoinsPerMonthWithNames</returns>
|
|
public async Task<List<CoinsPerYearWithNames>> GetYearlyTopAsync(int count, AppUserType appUserType, int year, decimal minBalance)
|
|
{
|
|
var coins = await _perYearNamesRepository.QueryView(c => c.AppUserType == appUserType && c.Year == year && c.Balance >= minBalance).OrderByDescending(c => c.Balance).ThenBy(c => c.LastUpdate).Take(count).ToListAsync();
|
|
return coins;
|
|
}
|
|
}
|
|
}
|