using System.Threading.Tasks; using Asp.Versioning; using AutoMapper; using gehGassi.Core.Interfaces; using gehGassi.Domain.Common; using gehGassi.Domain.Vouchers; using gehGassi.Dto; using gehGassi.Dto.Common; using gehGassi.Dto.Vouchers; using gehGassi.Web.Helper; using Microsoft.AspNetCore.Authentication.JwtBearer; using Microsoft.AspNetCore.Authorization; using Microsoft.AspNetCore.Hosting; using Microsoft.AspNetCore.Mvc; using Microsoft.Extensions.Hosting; using Microsoft.Extensions.Logging; using Microsoft.Extensions.Options; namespace gehGassi.Web.Controllers.Api { /// /// Controller für die Verwaltung von Gutscheinen /// [Authorize(AuthenticationSchemes = JwtBearerDefaults.AuthenticationScheme)] [ApiController] [ApiVersion(1)] [Route("api/vouchers")] [Route("api/v{v:apiVersion}/vouchers")] public class ApiVoucherController : ApiBaseController { private readonly ILogger _logger; private readonly IVoucherCampaignService _voucherCampaignService; private readonly IMangoPayService _mangoPayService; private readonly IWebHostEnvironment _hostEnvironment; private readonly IWalletService _walletService; private readonly IWalkService _walkService; private readonly ICustomerService _customerService; /// /// Erstellt eine Instanz /// /// Instanz eines IMapper /// Instanz eines ILogger /// Instanz von LocalizationOptions /// Instanz eines IAppUserService /// Instanz eines IVoucherCampaignService /// Instanz eines IMangoPayService /// Instanz eines IWebHostEnvironment /// Instanz eines IWalletService /// Instanz eines IWalkService /// Instanz eines ICustomerService public ApiVoucherController(IMapper mapper, ILogger logger, IOptions localizationOptions, IAppUserService appUserService, IVoucherCampaignService voucherCampaignService, IMangoPayService mangoPayService, IWebHostEnvironment hostEnvironment, IWalletService walletService, IWalkService walkService, ICustomerService customerService) : base(mapper, localizationOptions, appUserService) { _logger = logger; _voucherCampaignService = voucherCampaignService; _mangoPayService = mangoPayService; _hostEnvironment = hostEnvironment; _walletService = walletService; _walkService = walkService; _customerService = customerService; } /// /// Prüfen eines Gutscheincodes für einen AppUser /// /// Model mit Code und AppUserId /// HTTP 200 OK wenn erfolgreich [HttpPost] [Route("CheckVoucherCode")] public async Task CheckVoucherCode(CheckVoucherCodeDto dto) { var validationResult = await _voucherCampaignService.ValidateVoucherCodeAsync(dto.Code, dto.AppUserId); if (User?.Identity != null && User.Identity.IsAuthenticated) { if (ModelState.IsValid) { var result = new CheckVoucherCodeResultDto() { VoucherId = string.Empty, VoucherCampaignId = string.Empty, VoucherAmmount = 0, CampaignType = VoucherCampaignTypeDto.SingleVoucher, ValidationResult = (VoucherValidationResultDto)validationResult }; if (validationResult == VoucherValidationResult.Valid) { var voucher = await _voucherCampaignService.GetVoucherByCodeAsync(dto.Code); result.VoucherId = voucher.Id; result.VoucherCampaignId = voucher.VoucherCampaignId; result.VoucherAmmount = voucher.VoucherAmmount; var campaign = await _voucherCampaignService.GetAsync(voucher.VoucherCampaignId); if (campaign != null) { result.CampaignType = (VoucherCampaignTypeDto)campaign.CampaignType; //Nun noch das Budget gegen das Wallet prüfen if (!_hostEnvironment.IsDevelopment()) result.ValidationResult = (VoucherValidationResultDto)await CheckBalance(campaign.WalletCreditId, voucher.VoucherAmmount); } } return Ok(result); } } return BadRequest(CommunicationErrors.Common_Model_Invalid); } /// /// Holt einen Gutscheincode anhand des QR-Codes /// /// Model mit QR-Code /// HTTP 200 OK wenn erfolgreich [HttpPost] [Route("GetVoucherCodeByQrCode")] public async Task GetVoucherCodeByQrCode(GetVoucherByQrCodeDto dto) { if (User?.Identity != null && User.Identity.IsAuthenticated) { var result = new VoucherByQrCodeResultDto() { Exists = false, Code = string.Empty }; var voucher = await _voucherCampaignService.GetVoucherByQrCodeAsync(dto.QrCode); if (voucher != null) { result.Exists = true; result.Code = voucher.Code; } return Ok(result); } return BadRequest(CommunicationErrors.Common_Model_Invalid); } /// /// Reserviert einen Gutschein für einen Walk /// /// Model mit nötigen Daten /// HTTP 200 OK wenn erfolgreich [HttpPost] [Route("ReserveVoucher")] public async Task ReserveVoucher(ReserveVoucherDto dto) { var result = new ReserveVoucherResultDto() { Success = false, VoucherUsageId = -1 }; if (User?.Identity != null && User.Identity.IsAuthenticated) { if (ModelState.IsValid) { //1. Prüfen ob der Gutschein existiert und gültig ist var validationResult = await _voucherCampaignService.ValidateVoucherCodeAsync(dto.Code, dto.AppUserId); if (validationResult == VoucherValidationResult.Valid) { var voucher = await _voucherCampaignService.GetVoucherByCodeAsync(dto.Code); if (voucher != null && voucher.Id == dto.VoucherId) { var campaign = await _voucherCampaignService.GetAsync(voucher.VoucherCampaignId); if (campaign != null) { var customer = await _customerService.GetAsync(campaign.CustomerId); if (customer != null) { //2. Prüfen ob noch genug Budget in der Kampagne vorhanden ist validationResult = await CheckBalance(campaign.WalletCreditId, voucher.VoucherAmmount); if (validationResult == VoucherValidationResult.Valid) { //3. Geld vom Guthabenkonto der Kamapgne auf das Transferskonto überweisen mit Verweis auf den Walk und Transaktion erfassen var ammount = (int)(dto.Ammount * 100); var transferResult = await _mangoPayService.TransferMoneyAsync(customer.MangopayPaymentId, campaign.WalletCreditId, customer.MangopayPaymentId, campaign.WalletFeeId, dto.WalkId, ammount, 0, $"VoucherId_{voucher.Id}_WalkId_{dto.WalkId}", "", ""); if (transferResult.Success) { //4. Reservieren durch die Anlage einer VoucherUsage var voucherUsage = await _voucherCampaignService.ReserveVoucherAsync(voucher.Id, dto.AppUserId, dto.WalkId, voucher.VoucherAmmount, dto.Ammount); //5. Den Gutschein beim Walk eintragen await _walkService.AddVoucherToWalk(dto.WalkId, voucher.Id, dto.Ammount); //6. Usage in der Kampagne eintragen (VouchersUsed, BudgetUsed) campaign.VouchersUsed += 1; campaign.BudgetUsed += dto.Ammount; //7. Usage beim voucher eintragen (UsedCount, IsValid wenn Einzelgutschein) voucher.UsedCount += 1; voucher.IsValid = campaign.CampaignType != VoucherCampaignType.MultiVoucher; await _voucherCampaignService.CommitAsync(User.Identity.Name); result.Success = true; result.VoucherUsageId = voucherUsage.Id; } else { result.TransferFailed = true; } } } else { result.CustomerNotFound = true; } } else { result.CampaignNotFound = true; } } else { result.VoucherNotFound = true; } } result.ValidationResult = (VoucherValidationResultDto)validationResult; return Ok(result); } } return BadRequest(CommunicationErrors.Common_Model_Invalid); } /// /// Stornieren eines Gutscheins /// /// Model mit nötigen Daten /// HTTP 200 OK wenn erfolgreich [HttpPost] [Route("CancelVoucher")] public async Task CancelVoucher(CancelVoucherDto dto) { if (User?.Identity != null && User.Identity.IsAuthenticated) { if (ModelState.IsValid) { var usage = await _voucherCampaignService.GetUsageAsync(dto.VoucherId, dto.AppUserId, dto.WalkId); if (usage != null) { var voucher = await _voucherCampaignService.GetVoucherAsync(usage.VoucherId); if (voucher != null && voucher.Id == dto.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, dto.WalkId, ammount, 0, $"VoucherId_{voucher.Id}_WalkId_{dto.WalkId}", "", ""); 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; //Den Gutschein vom Walk entfernen await _walkService.RemoveVoucherFromWalk(dto.WalkId, voucher.Id); //Reservieren durch die Anlage einer VoucherUsage _voucherCampaignService.RemoveUsage(usage); await _voucherCampaignService.CommitAsync(User.Identity.Name); return Ok(); } } } } } return NotFound(CommunicationErrors.Common_NotFound); } } return BadRequest(CommunicationErrors.Common_Model_Invalid); } #region Private /// /// Prüft ob ein Wallet genug Guthaben hat /// /// Id des Wallets /// Minimum Guthaben /// VoucherValidationResultDto private async Task CheckBalance(string walletId, decimal minAmmount) { var wallet = await _walletService.GetAsync(walletId); if (wallet != null) { var mangoPayResult = await _mangoPayService.GetWalletBalanceAsync(wallet.WalletId); if (mangoPayResult.Success) { if ((decimal)(mangoPayResult.Value / 100) < minAmmount) { return VoucherValidationResult.CampaignBudgetUsedUp; } return VoucherValidationResult.Valid; } return VoucherValidationResult.Invalid; } return VoucherValidationResult.Invalid; } #endregion } }