mirror of
https://github.com/aljazceru/btcpayserver.git
synced 2025-12-18 22:44:29 +01:00
Add pull payment grouping options (#3177)
* Add grouping by payment methods * Add filtering by pull payment state * Hide "Archive" button for archived pull payments * Don't show payment methods bar if there is only one * Add "All" payment method option * Remove filtering by payment method * Update state queries to not run on the client * Add filtering by future pull payments
This commit is contained in:
@@ -5,6 +5,13 @@ using Newtonsoft.Json;
|
|||||||
|
|
||||||
namespace BTCPayServer.Client.Models
|
namespace BTCPayServer.Client.Models
|
||||||
{
|
{
|
||||||
|
public enum PullPaymentState
|
||||||
|
{
|
||||||
|
Active,
|
||||||
|
Expired,
|
||||||
|
Archived,
|
||||||
|
Future
|
||||||
|
}
|
||||||
public class PullPaymentData
|
public class PullPaymentData
|
||||||
{
|
{
|
||||||
[JsonConverter(typeof(NBitcoin.JsonConverters.DateTimeToUnixTimeConverter))]
|
[JsonConverter(typeof(NBitcoin.JsonConverters.DateTimeToUnixTimeConverter))]
|
||||||
|
|||||||
@@ -147,15 +147,19 @@ namespace BTCPayServer.Controllers
|
|||||||
}
|
}
|
||||||
|
|
||||||
[HttpGet("")]
|
[HttpGet("")]
|
||||||
public async Task<IActionResult> PullPayments(string storeId, int skip = 0, int count = 50,
|
public async Task<IActionResult> PullPayments(
|
||||||
string sortOrder = "desc")
|
string storeId,
|
||||||
|
PullPaymentState pullPaymentState,
|
||||||
|
int skip = 0,
|
||||||
|
int count = 50,
|
||||||
|
string sortOrder = "desc"
|
||||||
|
)
|
||||||
{
|
{
|
||||||
await using var ctx = _dbContextFactory.CreateContext();
|
await using var ctx = _dbContextFactory.CreateContext();
|
||||||
var now = DateTimeOffset.UtcNow;
|
var now = DateTimeOffset.UtcNow;
|
||||||
var ppsQuery = ctx.PullPayments
|
var ppsQuery = ctx.PullPayments
|
||||||
.Include(data => data.Payouts)
|
.Include(data => data.Payouts)
|
||||||
.Where(p => p.StoreId == storeId && !p.Archived);
|
.Where(p => p.StoreId == storeId);
|
||||||
|
|
||||||
|
|
||||||
if (sortOrder != null)
|
if (sortOrder != null)
|
||||||
{
|
{
|
||||||
@@ -172,12 +176,45 @@ namespace BTCPayServer.Controllers
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
var paymentMethods = await _payoutHandlers.GetSupportedPaymentMethods(HttpContext.GetStoreData());
|
||||||
|
if (!paymentMethods.Any())
|
||||||
|
{
|
||||||
|
TempData.SetStatusMessageModel(new StatusMessageModel
|
||||||
|
{
|
||||||
|
Message = "You must enable at least one payment method before creating a pull payment.",
|
||||||
|
Severity = StatusMessageModel.StatusSeverity.Error
|
||||||
|
});
|
||||||
|
return RedirectToAction("PaymentMethods", "Stores", new { storeId });
|
||||||
|
}
|
||||||
|
|
||||||
var vm = this.ParseListQuery(new PullPaymentsModel()
|
var vm = this.ParseListQuery(new PullPaymentsModel()
|
||||||
{
|
{
|
||||||
Skip = skip,
|
Skip = skip,
|
||||||
Count = count,
|
Count = count,
|
||||||
Total = await ppsQuery.CountAsync()
|
Total = await ppsQuery.CountAsync(),
|
||||||
|
ActiveState = pullPaymentState
|
||||||
});
|
});
|
||||||
|
|
||||||
|
switch (pullPaymentState) {
|
||||||
|
case PullPaymentState.Active:
|
||||||
|
ppsQuery = ppsQuery
|
||||||
|
.Where(
|
||||||
|
p => !p.Archived &&
|
||||||
|
(p.EndDate != null ? p.EndDate > DateTimeOffset.UtcNow : true) &&
|
||||||
|
p.StartDate <= DateTimeOffset.UtcNow
|
||||||
|
);
|
||||||
|
break;
|
||||||
|
case PullPaymentState.Archived:
|
||||||
|
ppsQuery = ppsQuery.Where(p => p.Archived);
|
||||||
|
break;
|
||||||
|
case PullPaymentState.Expired:
|
||||||
|
ppsQuery = ppsQuery.Where(p => DateTimeOffset.UtcNow > p.EndDate);
|
||||||
|
break;
|
||||||
|
case PullPaymentState.Future:
|
||||||
|
ppsQuery = ppsQuery.Where(p => p.StartDate > DateTimeOffset.UtcNow);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
var pps = (await ppsQuery
|
var pps = (await ppsQuery
|
||||||
.Skip(vm.Skip)
|
.Skip(vm.Skip)
|
||||||
.Take(vm.Count)
|
.Take(vm.Count)
|
||||||
@@ -210,8 +247,9 @@ namespace BTCPayServer.Controllers
|
|||||||
Completed = totalCompleted.RoundToSignificant(ni.Divisibility).ToString("C", nfi),
|
Completed = totalCompleted.RoundToSignificant(ni.Divisibility).ToString("C", nfi),
|
||||||
Limit = _currencyNameTable.DisplayFormatCurrency(ppBlob.Limit, ppBlob.Currency),
|
Limit = _currencyNameTable.DisplayFormatCurrency(ppBlob.Limit, ppBlob.Currency),
|
||||||
ResetIn = period?.End is DateTimeOffset nr ? ZeroIfNegative(nr - now).TimeString() : null,
|
ResetIn = period?.End is DateTimeOffset nr ? ZeroIfNegative(nr - now).TimeString() : null,
|
||||||
EndIn = pp.EndDate is DateTimeOffset end ? ZeroIfNegative(end - now).TimeString() : null
|
EndIn = pp.EndDate is DateTimeOffset end ? ZeroIfNegative(end - now).TimeString() : null,
|
||||||
}
|
},
|
||||||
|
Archived = pp.Archived
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
return View(vm);
|
return View(vm);
|
||||||
|
|||||||
@@ -3,6 +3,8 @@ using System.Collections.Generic;
|
|||||||
using System.ComponentModel;
|
using System.ComponentModel;
|
||||||
using System.ComponentModel.DataAnnotations;
|
using System.ComponentModel.DataAnnotations;
|
||||||
using Microsoft.AspNetCore.Mvc.Rendering;
|
using Microsoft.AspNetCore.Mvc.Rendering;
|
||||||
|
using BTCPayServer.Payments;
|
||||||
|
using BTCPayServer.Client.Models;
|
||||||
|
|
||||||
namespace BTCPayServer.Models.WalletViewModels
|
namespace BTCPayServer.Models.WalletViewModels
|
||||||
{
|
{
|
||||||
@@ -26,9 +28,13 @@ namespace BTCPayServer.Models.WalletViewModels
|
|||||||
public ProgressModel Progress { get; set; }
|
public ProgressModel Progress { get; set; }
|
||||||
public DateTimeOffset StartDate { get; set; }
|
public DateTimeOffset StartDate { get; set; }
|
||||||
public DateTimeOffset? EndDate { get; set; }
|
public DateTimeOffset? EndDate { get; set; }
|
||||||
|
public bool Archived { get; set; } = false;
|
||||||
}
|
}
|
||||||
|
|
||||||
public List<PullPaymentModel> PullPayments { get; set; } = new List<PullPaymentModel>();
|
public List<PullPaymentModel> PullPayments { get; set; } = new List<PullPaymentModel>();
|
||||||
|
public string PaymentMethodId { get; set; }
|
||||||
|
public IEnumerable<PaymentMethodId> PaymentMethods { get; set; }
|
||||||
|
public PullPaymentState ActiveState { get; set; } = PullPaymentState.Active;
|
||||||
}
|
}
|
||||||
|
|
||||||
public class NewPullPaymentModel
|
public class NewPullPaymentModel
|
||||||
|
|||||||
@@ -1,6 +1,7 @@
|
|||||||
@using BTCPayServer.Views.Stores
|
@using BTCPayServer.Views.Stores
|
||||||
@using BTCPayServer.Abstractions.Extensions
|
@using BTCPayServer.Abstractions.Extensions
|
||||||
@using BTCPayServer.Client
|
@using BTCPayServer.Client
|
||||||
|
@using BTCPayServer.Client.Models
|
||||||
@model BTCPayServer.Models.WalletViewModels.PullPaymentsModel
|
@model BTCPayServer.Models.WalletViewModels.PullPaymentsModel
|
||||||
@{
|
@{
|
||||||
ViewData.SetActivePage(StoreNavPages.PullPayments, "Pull Payments", Context.GetStoreData().Id);
|
ViewData.SetActivePage(StoreNavPages.PullPayments, "Pull Payments", Context.GetStoreData().Id);
|
||||||
@@ -50,6 +51,19 @@
|
|||||||
</a>
|
</a>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
|
<ul class="nav nav-pills border bg-tile" style="border-radius: 4px;">
|
||||||
|
@foreach (var state in Enum.GetValues(typeof(PullPaymentState)).Cast<PullPaymentState>())
|
||||||
|
{
|
||||||
|
<li class="nav-item py-0">
|
||||||
|
<a id="@state-view"
|
||||||
|
asp-action="PullPayments"
|
||||||
|
asp-route-storeId="@Context.GetRouteValue("storeId")"
|
||||||
|
asp-route-pullPaymentState="@state"
|
||||||
|
class="nav-link me-1 @(state == Model.ActiveState ? "active" : "")" role="tab">@state</a>
|
||||||
|
</li>
|
||||||
|
}
|
||||||
|
</ul>
|
||||||
|
|
||||||
@if (Model.PullPayments.Any())
|
@if (Model.PullPayments.Any())
|
||||||
{
|
{
|
||||||
<div class="row">
|
<div class="row">
|
||||||
@@ -81,6 +95,7 @@
|
|||||||
<a
|
<a
|
||||||
asp-action="PullPayments"
|
asp-action="PullPayments"
|
||||||
asp-route-sortOrder="@(nextStartDateSortOrder ?? "asc")"
|
asp-route-sortOrder="@(nextStartDateSortOrder ?? "asc")"
|
||||||
|
asp-route-pullPaymentState="@Model.ActiveState"
|
||||||
class="text-nowrap"
|
class="text-nowrap"
|
||||||
title="@(nextStartDateSortOrder == "desc" ? sortByAsc : sortByDesc)">
|
title="@(nextStartDateSortOrder == "desc" ? sortByAsc : sortByDesc)">
|
||||||
Start
|
Start
|
||||||
@@ -120,6 +135,8 @@
|
|||||||
asp-route-pullPaymentId="@pp.Id">
|
asp-route-pullPaymentId="@pp.Id">
|
||||||
Payouts
|
Payouts
|
||||||
</a>
|
</a>
|
||||||
|
@if (!pp.Archived)
|
||||||
|
{
|
||||||
<span permission="@Policies.CanModifyStoreSettings"> - </span>
|
<span permission="@Policies.CanModifyStoreSettings"> - </span>
|
||||||
<a asp-action="ArchivePullPayment"
|
<a asp-action="ArchivePullPayment"
|
||||||
permission="@Policies.CanModifyStoreSettings"
|
permission="@Policies.CanModifyStoreSettings"
|
||||||
@@ -130,6 +147,7 @@
|
|||||||
data-description="Do you really want to archive the pull payment <strong>@pp.Name</strong>?">
|
data-description="Do you really want to archive the pull payment <strong>@pp.Name</strong>?">
|
||||||
Archive
|
Archive
|
||||||
</a>
|
</a>
|
||||||
|
}
|
||||||
</td>
|
</td>
|
||||||
</tr>
|
</tr>
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user