mirror of
https://github.com/aljazceru/btcpayserver.git
synced 2025-12-17 22:14:26 +01:00
work on building the viewmodel for crowdfund
This commit is contained in:
@@ -8,13 +8,16 @@ using System.Threading.Tasks;
|
||||
using BTCPayServer.Data;
|
||||
using BTCPayServer.Filters;
|
||||
using BTCPayServer.Models.AppViewModels;
|
||||
using BTCPayServer.Rating;
|
||||
using BTCPayServer.Security;
|
||||
using BTCPayServer.Services.Apps;
|
||||
using BTCPayServer.Services.Invoices;
|
||||
using BTCPayServer.Services.Rates;
|
||||
using Microsoft.AspNetCore.Authorization;
|
||||
using Microsoft.AspNetCore.Cors;
|
||||
using Microsoft.AspNetCore.Mvc;
|
||||
using Microsoft.EntityFrameworkCore;
|
||||
using NBitpayClient;
|
||||
using YamlDotNet.RepresentationModel;
|
||||
using static BTCPayServer.Controllers.AppsController;
|
||||
|
||||
@@ -22,14 +25,24 @@ namespace BTCPayServer.Controllers
|
||||
{
|
||||
public class AppsPublicController : Controller
|
||||
{
|
||||
public AppsPublicController(AppsHelper appsHelper, InvoiceController invoiceController)
|
||||
public AppsPublicController(AppsHelper appsHelper,
|
||||
InvoiceController invoiceController,
|
||||
RateFetcher rateFetcher,
|
||||
BTCPayNetworkProvider btcPayNetworkProvider,
|
||||
InvoiceRepository invoiceRepository)
|
||||
{
|
||||
_AppsHelper = appsHelper;
|
||||
_InvoiceController = invoiceController;
|
||||
_rateFetcher = rateFetcher;
|
||||
_btcPayNetworkProvider = btcPayNetworkProvider;
|
||||
_invoiceRepository = invoiceRepository;
|
||||
}
|
||||
|
||||
private AppsHelper _AppsHelper;
|
||||
private InvoiceController _InvoiceController;
|
||||
private readonly RateFetcher _rateFetcher;
|
||||
private readonly BTCPayNetworkProvider _btcPayNetworkProvider;
|
||||
private readonly InvoiceRepository _invoiceRepository;
|
||||
|
||||
[HttpGet]
|
||||
[Route("/apps/{appId}/pos")]
|
||||
@@ -80,15 +93,40 @@ namespace BTCPayServer.Controllers
|
||||
return NotFound();
|
||||
var settings = app.GetSettings<CrowdfundSettings>();
|
||||
var currency = _AppsHelper.GetCurrencyData(settings.TargetCurrency, false);
|
||||
double step = currency == null ? 1 : Math.Pow(10, -(currency.Divisibility));
|
||||
|
||||
var numberFormatInfo = _AppsHelper.Currencies.GetNumberFormatInfo(currency.Code) ?? _AppsHelper.Currencies.GetNumberFormatInfo("USD");
|
||||
return View(new ViewCrowdfundViewModel()
|
||||
return View(CrowdfundHelper.GetInfo(app, _invoiceRepository, _rateFetcher, _btcPayNetworkProvider ));
|
||||
}
|
||||
|
||||
[HttpPost]
|
||||
[Route("/apps/{appId}/crowdfund/contribute")]
|
||||
[XFrameOptionsAttribute(null)]
|
||||
[IgnoreAntiforgeryToken]
|
||||
[EnableCors(CorsPolicies.All)]
|
||||
public async Task<IActionResult> ContributeToCrowdfund(string appId,[FromBody]ContributeToCrowdfund request, [FromQuery]bool redirectToCheckout)
|
||||
{
|
||||
Title = settings.Title,
|
||||
CustomCSSLink = settings.CustomCSSLink
|
||||
var app = await _AppsHelper.GetApp(appId, AppType.Crowdfund);
|
||||
if (app == null)
|
||||
return NotFound();
|
||||
var settings = app.GetSettings<CrowdfundSettings>();
|
||||
var currency = _AppsHelper.GetCurrencyData(settings.TargetCurrency, false);
|
||||
var store = await _AppsHelper.GetStore(app);
|
||||
var invoice = await _InvoiceController.CreateInvoiceCore(new Invoice()
|
||||
{
|
||||
|
||||
}, store, HttpContext.Request.GetAbsoluteRoot());
|
||||
if (redirectToCheckout)
|
||||
{
|
||||
return RedirectToAction(nameof(InvoiceController.Checkout), "Invoice", new { invoiceId = invoice.Data.Id });
|
||||
}
|
||||
else
|
||||
{
|
||||
return Json(new
|
||||
{
|
||||
InvoiceId = invoice.Data.Id
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
[HttpPost]
|
||||
[Route("/apps/{appId}/pos")]
|
||||
@@ -152,6 +190,84 @@ namespace BTCPayServer.Controllers
|
||||
}
|
||||
}
|
||||
|
||||
public class CrowdfundHelper
|
||||
{
|
||||
private static async Task<decimal> GetCurrentContributionAmount(InvoiceEntity[] invoices, string primaryCurrency,
|
||||
RateFetcher rateFetcher, RateRules rateRules)
|
||||
{
|
||||
decimal result = 0;
|
||||
|
||||
var groupingByCurrency = invoices.GroupBy(entity => entity.ProductInformation.Currency);
|
||||
|
||||
var ratesTask = rateFetcher.FetchRates(
|
||||
groupingByCurrency
|
||||
.Select((entities) => new CurrencyPair(entities.Key, primaryCurrency))
|
||||
.ToHashSet(),
|
||||
rateRules);
|
||||
|
||||
var finalTasks = new List<Task>();
|
||||
foreach (var rateTask in ratesTask)
|
||||
{
|
||||
finalTasks.Add(rateTask.Value.ContinueWith(task =>
|
||||
{
|
||||
var rate = task.Result.BidAsk?.Bid;
|
||||
if (rate == null) return;
|
||||
var currencyGroup = groupingByCurrency.Single(entities => entities.Key == rateTask.Key.Left);
|
||||
result += currencyGroup.Sum(entity => entity.ProductInformation.Price / rate.Value);
|
||||
}));
|
||||
}
|
||||
|
||||
await Task.WhenAll(finalTasks);
|
||||
|
||||
return result;
|
||||
|
||||
}
|
||||
|
||||
public static async Task<ViewCrowdfundViewModel> GetInfo(AppData appData, InvoiceRepository invoiceRepository,
|
||||
RateFetcher rateFetcher, BTCPayNetworkProvider btcPayNetworkProvider)
|
||||
{
|
||||
var settings = appData.GetSettings<CrowdfundSettings>();
|
||||
var invoices = await GetPaidInvoicesForApp(appData, invoiceRepository);
|
||||
var rateRules = appData.StoreData.GetStoreBlob().GetRateRules(btcPayNetworkProvider);
|
||||
var currentAmount = await GetCurrentContributionAmount(
|
||||
invoices,
|
||||
settings.TargetCurrency, rateFetcher, rateRules);
|
||||
var paidInvoices = invoices.Length;
|
||||
var active = (settings.StartDate == null || DateTime.UtcNow >= settings.StartDate) &&
|
||||
(settings.EndDate == null || DateTime.UtcNow <= settings.EndDate) &&
|
||||
(!settings.EnforceTargetAmount || settings.TargetAmount > currentAmount)
|
||||
|
||||
return new ViewCrowdfundViewModel()
|
||||
{
|
||||
Title = settings.Title,
|
||||
Description = settings.Description,
|
||||
CustomCSSLink = settings.CustomCSSLink,
|
||||
StoreId = appData.StoreDataId,
|
||||
AppId = appData.Id,
|
||||
StartDate = settings.StartDate,
|
||||
EndDate = settings.EndDate,
|
||||
TargetAmount = settings.TargetAmount,
|
||||
TargetCurrency = settings.TargetCurrency,
|
||||
EnforceTargetAmount = settings.EnforceTargetAmount,
|
||||
Info = new ViewCrowdfundViewModel.CrowdfundInfo()
|
||||
{
|
||||
TotalContributors = paidInvoices,
|
||||
CurrentAmount = currentAmount,
|
||||
Active = active
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
private static async Task<InvoiceEntity[]> GetPaidInvoicesForApp(AppData appData, InvoiceRepository invoiceRepository)
|
||||
{
|
||||
return await invoiceRepository.GetInvoices(new InvoiceQuery()
|
||||
{
|
||||
OrderId = appData.Id,
|
||||
Status = new string[]{ InvoiceState.ToString(InvoiceStatus.Complete)}
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
public class AppsHelper
|
||||
{
|
||||
|
||||
@@ -15,11 +15,9 @@ namespace BTCPayServer.Models.AppViewModels
|
||||
[Required]
|
||||
public bool Enabled { get; set; }
|
||||
|
||||
|
||||
public DateTime? StartDate { get; set; }
|
||||
public DateTime? EndDate { get; set; }
|
||||
|
||||
|
||||
[Required]
|
||||
[MaxLength(5)]
|
||||
[Display(Name = "The primary currency used for targets and stats")]
|
||||
|
||||
@@ -1,8 +1,39 @@
|
||||
namespace BTCPayServer.Models.AppViewModels
|
||||
using System;
|
||||
using System.ComponentModel.DataAnnotations;
|
||||
|
||||
namespace BTCPayServer.Models.AppViewModels
|
||||
{
|
||||
public class ViewCrowdfundViewModel
|
||||
{
|
||||
public string StatusMessage{ get; set; }
|
||||
public string StoreId { get; set; }
|
||||
public string AppId { get; set; }
|
||||
public string Title { get; set; }
|
||||
public string Description { get; set; }
|
||||
public string CustomCSSLink { get; set; }
|
||||
public DateTime? StartDate { get; set; }
|
||||
public DateTime? EndDate { get; set; }
|
||||
|
||||
public string TargetCurrency { get; set; }
|
||||
public decimal? TargetAmount { get; set; }
|
||||
public bool EnforceTargetAmount { get; set; }
|
||||
|
||||
public CrowdfundInfo Info { get; set; }
|
||||
|
||||
|
||||
public class CrowdfundInfo
|
||||
{
|
||||
public int TotalContributors { get; set; }
|
||||
public decimal CurrentAmount { get; set; }
|
||||
public bool Active { get; set; }
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
public class ContributeToCrowdfund
|
||||
{
|
||||
[Required] public decimal Amount { get; set; }
|
||||
public string Email { get; set; }
|
||||
}
|
||||
}
|
||||
|
||||
@@ -0,0 +1,8 @@
|
||||
@model BTCPayServer.Models.AppViewModels.ContributeToCrowdfund
|
||||
|
||||
|
||||
<form method="post" action="contribute">
|
||||
<input asp-for="Email" type="email"/>
|
||||
<input asp-for="Amount" type="number" step="any" />
|
||||
<button type="submit">Contribute</button>
|
||||
</form>
|
||||
@@ -0,0 +1,19 @@
|
||||
@model BTCPayServer.Models.AppViewModels.ViewCrowdfundViewModel
|
||||
<div class="container d-flex h-100">
|
||||
|
||||
<div class="row">
|
||||
<div class="col-lg-12 text-center">
|
||||
<partial name="_StatusMessage" for="@Model.StatusMessage"/>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<header>
|
||||
<h1>@Model.Title</h1>
|
||||
</header>
|
||||
<main>
|
||||
@Model.Description
|
||||
<partial name="ContributeForm"/>
|
||||
</main>
|
||||
<footer></footer>
|
||||
<pre> @Html.Raw(Model)</pre>
|
||||
</div>
|
||||
@@ -1,6 +1,7 @@
|
||||
@addTagHelper *, Meziantou.AspNetCore.BundleTagHelpers
|
||||
@inject BTCPayServer.HostedServices.CssThemeManager themeManager
|
||||
|
||||
@using System.Security.AccessControl
|
||||
@model BTCPayServer.Models.AppViewModels.ViewCrowdfundViewModel
|
||||
@{
|
||||
ViewData["Title"] = Model.Title;
|
||||
@@ -11,18 +12,22 @@
|
||||
<html class="h-100">
|
||||
<head>
|
||||
<title>@Model.Title</title>
|
||||
<meta charset="utf-8" />
|
||||
<meta charset="utf-8"/>
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1">
|
||||
<meta name="apple-mobile-web-app-capable" content="yes">
|
||||
<link href="@this.Context.Request.GetAbsoluteUri(themeManager.BootstrapUri)" rel="stylesheet" />
|
||||
<link href="@this.Context.Request.GetAbsoluteUri(themeManager.BootstrapUri)" rel="stylesheet"/>
|
||||
@if (Model.CustomCSSLink != null)
|
||||
{
|
||||
<link href="@Model.CustomCSSLink" rel="stylesheet" />
|
||||
<link href="@Model.CustomCSSLink" rel="stylesheet"/>
|
||||
}
|
||||
<link href="~/vendor/font-awesome/css/font-awesome.min.css" rel="stylesheet" />
|
||||
<link href="~/vendor/font-awesome/css/font-awesome.min.css" rel="stylesheet"/>
|
||||
<bundle name="wwwroot/bundles/crowdfund-bundle.min.js"></bundle>
|
||||
<script>
|
||||
var srvModel = @Html.Raw(Model);
|
||||
|
||||
</script>
|
||||
</head>
|
||||
<body class="h-100">
|
||||
|
||||
<partial name="MinimalCrowdfund" model="@Model"/>
|
||||
</body>
|
||||
</html>
|
||||
|
||||
@@ -61,5 +61,13 @@
|
||||
"wwwroot/cart/js/cart.js",
|
||||
"wwwroot/cart/js/cart.jquery.js"
|
||||
]
|
||||
},
|
||||
{
|
||||
"outputFileName": "wwwroot/bundles/crowdfund-bundle.min.js",
|
||||
"inputFiles": [
|
||||
"wwwroot/vendor/jquery/jquery.js",
|
||||
"wwwroot/vendor/bootstrap4/js/bootstrap.js",
|
||||
"wwwroot/modal/btcpay.js"
|
||||
]
|
||||
}
|
||||
]
|
||||
|
||||
Reference in New Issue
Block a user