Add gift code redeem

This commit is contained in:
Marcel Baumgartner 2023-10-24 11:13:06 +02:00
parent 863a002370
commit d0f03a19a2
5 changed files with 140 additions and 14 deletions

View file

@ -0,0 +1,60 @@
using Microsoft.EntityFrameworkCore;
using Moonlight.App.Database.Entities;
using Moonlight.App.Database.Entities.Store;
using Moonlight.App.Exceptions;
using Moonlight.App.Repositories;
namespace Moonlight.App.Services.Store;
public class StoreGiftService
{
private readonly IServiceScopeFactory ServiceScopeFactory;
public StoreGiftService(IServiceScopeFactory serviceScopeFactory)
{
ServiceScopeFactory = serviceScopeFactory;
}
public async Task Redeem(User u, string code)
{
using var scope = ServiceScopeFactory.CreateScope();
var giftCodeRepo = scope.ServiceProvider.GetRequiredService<Repository<GiftCode>>();
var userRepo = scope.ServiceProvider.GetRequiredService<Repository<User>>();
var user = userRepo
.Get()
.Include(x => x.GiftCodeUses)
.ThenInclude(x => x.GiftCode)
.FirstOrDefault(x => x.Id == u.Id);
if(user == null)
throw new DisplayException("Unsafe value detected. Please reload the page to proceed");
var giftCode = giftCodeRepo
.Get()
.FirstOrDefault(x => x.Code == code);
if (giftCode == null)
throw new DisplayException("The gift code does not exist");
if (giftCode.Amount < 1)
throw new DisplayException("The gift code can no longer be used as it has exceeded the max use amount");
if (user.GiftCodeUses.Any(x => x.GiftCode.Id == giftCode.Id))
throw new DisplayException("The gift code has already been used on this account");
giftCode.Amount--;
giftCodeRepo.Update(giftCode);
var giftCardUse = new GiftCodeUse()
{
GiftCode = giftCode
};
user.GiftCodeUses.Add(giftCardUse);
userRepo.Update(user);
var transactionService = scope.ServiceProvider.GetRequiredService<TransactionService>();
await transactionService.Add(u, giftCode.Value, $"Redeemed gift code '{giftCode.Code}'");
}
}

View file

@ -0,0 +1,14 @@
using Moonlight.App.Models.Abstractions;
namespace Moonlight.App.Services.Store;
public class StorePaymentService
{
public readonly List<PaymentGateway> Gateways = new();
public Task RegisterGateway(PaymentGateway gateway)
{
Gateways.Add(gateway);
return Task.CompletedTask;
}
}

View file

@ -8,16 +8,11 @@ public class StoreService
public StoreAdminService Admin => ServiceProvider.GetRequiredService<StoreAdminService>(); public StoreAdminService Admin => ServiceProvider.GetRequiredService<StoreAdminService>();
public StoreOrderService Order => ServiceProvider.GetRequiredService<StoreOrderService>(); public StoreOrderService Order => ServiceProvider.GetRequiredService<StoreOrderService>();
public readonly List<PaymentGateway> Gateways = new(); public StorePaymentService Payment => ServiceProvider.GetRequiredService<StorePaymentService>();
public StoreGiftService Gift => ServiceProvider.GetRequiredService<StoreGiftService>();
public StoreService(IServiceProvider serviceProvider) public StoreService(IServiceProvider serviceProvider)
{ {
ServiceProvider = serviceProvider; ServiceProvider = serviceProvider;
} }
public Task RegisterGateway(PaymentGateway gateway)
{
Gateways.Add(gateway);
return Task.CompletedTask;
}
} }

View file

@ -51,9 +51,11 @@ builder.Services.AddScoped<ModalService>();
builder.Services.AddScoped<AlertService>(); builder.Services.AddScoped<AlertService>();
// Services / Store // Services / Store
builder.Services.AddSingleton<StoreService>(); builder.Services.AddScoped<StoreService>();
builder.Services.AddScoped<StoreAdminService>(); builder.Services.AddScoped<StoreAdminService>();
builder.Services.AddScoped<StoreOrderService>(); builder.Services.AddScoped<StoreOrderService>();
builder.Services.AddScoped<StoreGiftService>();
builder.Services.AddSingleton<StorePaymentService>();
builder.Services.AddScoped<TransactionService>(); builder.Services.AddScoped<TransactionService>();
// Services / Users // Services / Users

View file

@ -3,33 +3,52 @@
@using Moonlight.App.Services @using Moonlight.App.Services
@using Moonlight.App.Database.Entities.Store @using Moonlight.App.Database.Entities.Store
@using BlazorTable @using BlazorTable
@using Moonlight.App.Models.Abstractions
@using Moonlight.App.Services.Store @using Moonlight.App.Services.Store
@inject IdentityService IdentityService @inject IdentityService IdentityService
@inject ConfigService ConfigService @inject ConfigService ConfigService
@inject StoreService StoreService @inject StoreService StoreService
@inject ToastService ToastService
@inject NavigationManager Navigation
<AccountNavigation Index="2"/> <AccountNavigation Index="2"/>
<div class="row mt-5"> <div class="row mt-5">
<div class="col-md-6 col-12"> <div class="col-md-6 col-12">
<div class="card card-body"> <div class="card">
<div class="card-header">
<h3 class="card-title">Redeem gift code</h3>
</div>
<div class="card-body">
<div class="input-group">
<input @bind="GiftCode" class="form-control form-control-solid-bg" placeholder="Gift code..."/>
<WButton OnClick="RedeemGiftCode" Text="Redeem" WorkingText="Checking" CssClasses="btn btn-primary"/>
</div>
</div>
</div> </div>
</div> </div>
<div class="col-md-6 col-12"> <div class="col-md-6 col-12">
<div class="card card-body"> <div class="card card-body">
<div class="row"> <div class="row d-flex justify-content-center">
@foreach (var gateway in StoreService.Gateways) <input @bind="Amount" class="form-control form-control-lg form-control-solid-bg w-50 text-center fs-2" placeholder="Enter amount to add to your account"/>
</div>
<div class="row mt-5 d-flex justify-content-center">
@foreach (var gateway in StoreService.Payment.Gateways)
{ {
<div class="col-md-4 col-12"> <div class="col-md-4 col-12">
<a @onclick:preventDefault href="#" class="card card-body bg-hover-info text-center border border-info"> <a @onclick="() => SelectGateway(gateway)" @onclick:preventDefault href="#" class="card card-body bg-hover-info text-center border border-info @(SelectedGateway == gateway ? "bg-info" : "")">
<i class="@(gateway.Icon)"></i> <i class="@(gateway.Icon)"></i>
<h4 class="fw-bold mb-0 align-middle">@(gateway.Name)</h4> <h4 class="fw-bold mb-0 align-middle">@(gateway.Name)</h4>
</a> </a>
</div> </div>
} }
</div> </div>
<div class="row mt-5">
<div class="text-center">
<WButton OnClick="LaunchPayment" Text="Add balance to your account" CssClasses="btn btn-primary"/>
</div>
</div>
</div> </div>
</div> </div>
</div> </div>
@ -39,7 +58,7 @@
<h3 class="card-title">Transactions</h3> <h3 class="card-title">Transactions</h3>
</div> </div>
<div class="card-body"> <div class="card-body">
<LazyLoader Load="Load"> <LazyLoader @ref="LazyLoader" Load="Load">
<Table TableItem="Transaction" <Table TableItem="Transaction"
Items="Transactions" Items="Transactions"
PageSize="50" PageSize="50"
@ -71,10 +90,46 @@
@code @code
{ {
private LazyLoader LazyLoader;
private Transaction[] Transactions; private Transaction[] Transactions;
private string GiftCode = "";
private double Amount = 0;
private PaymentGateway? SelectedGateway;
private async Task Load(LazyLoader _) private async Task Load(LazyLoader _)
{ {
Transactions = await IdentityService.GetTransactions(); Transactions = await IdentityService.GetTransactions();
Transactions = Transactions
.OrderByDescending(x => x.Id)
.ToArray();
}
private async Task RedeemGiftCode()
{
if (string.IsNullOrEmpty(GiftCode))
return;
await StoreService.Gift.Redeem(IdentityService.CurrentUser, GiftCode);
GiftCode = "";
await ToastService.Success("Successfully applied gift code");
await LazyLoader.Reload();
}
private async Task SelectGateway(PaymentGateway gateway)
{
SelectedGateway = gateway;
await InvokeAsync(StateHasChanged);
}
private async Task LaunchPayment()
{
if (SelectedGateway == null)
return;
var url = await SelectedGateway.Start(Amount);
Navigation.NavigateTo(url, true);
} }
} }