diff --git a/BTCPayServer.Client/Models/PaymentRequestBaseData.cs b/BTCPayServer.Client/Models/PaymentRequestBaseData.cs
index d425f61d0..6803d7833 100644
--- a/BTCPayServer.Client/Models/PaymentRequestBaseData.cs
+++ b/BTCPayServer.Client/Models/PaymentRequestBaseData.cs
@@ -37,6 +37,10 @@ namespace BTCPayServer.Client.Models
public string Title { get; set; }
public string Description { get; set; }
public string Email { get; set; }
+ ///
+ /// Linking to invoices outside BTCPay Server using & user defined ids
+ ///
+ public string ReferenceId { get; set; }
public bool AllowCustomPaymentAmounts { get; set; }
[JsonConverter(typeof(StringEnumConverter))]
diff --git a/BTCPayServer.Client/Models/WebhookEventType.cs b/BTCPayServer.Client/Models/WebhookEventType.cs
index ed2d431c4..b7c1e6bcb 100644
--- a/BTCPayServer.Client/Models/WebhookEventType.cs
+++ b/BTCPayServer.Client/Models/WebhookEventType.cs
@@ -17,5 +17,6 @@ public static class WebhookEventType
public const string PaymentRequestCreated = nameof(PaymentRequestCreated);
public const string PaymentRequestArchived = nameof(PaymentRequestArchived);
public const string PaymentRequestStatusChanged = nameof(PaymentRequestStatusChanged);
+ public const string PaymentRequestCompleted = nameof(PaymentRequestCompleted);
}
diff --git a/BTCPayServer.Data/Data/PaymentRequestData.cs b/BTCPayServer.Data/Data/PaymentRequestData.cs
index da4c3df27..943e64dc2 100644
--- a/BTCPayServer.Data/Data/PaymentRequestData.cs
+++ b/BTCPayServer.Data/Data/PaymentRequestData.cs
@@ -1,4 +1,5 @@
using System;
+using System.ComponentModel.DataAnnotations;
using System.ComponentModel.DataAnnotations.Schema;
using BTCPayServer.Client.Models;
using Microsoft.EntityFrameworkCore;
@@ -16,6 +17,11 @@ namespace BTCPayServer.Data
public string Currency { get; set; }
public decimal Amount { get; set; }
+ ///
+ /// Linking to invoices outside BTCPay Server using & user defined ids
+ ///
+ public string ReferenceId { get; set; }
+
public StoreData StoreData { get; set; }
public Client.Models.PaymentRequestStatus Status { get; set; }
diff --git a/BTCPayServer.Data/Migrations/20250415235643_AddingReferenceIdToPaymentRequest.cs b/BTCPayServer.Data/Migrations/20250415235643_AddingReferenceIdToPaymentRequest.cs
new file mode 100644
index 000000000..f32b26812
--- /dev/null
+++ b/BTCPayServer.Data/Migrations/20250415235643_AddingReferenceIdToPaymentRequest.cs
@@ -0,0 +1,34 @@
+using Microsoft.EntityFrameworkCore.Infrastructure;
+using Microsoft.EntityFrameworkCore.Migrations;
+
+#nullable disable
+
+namespace BTCPayServer.Data.Migrations
+{
+ [DbContext(typeof(ApplicationDbContext))]
+ [Migration("20250407133937_AddingReferenceIdToPaymentRequest")]
+ public partial class AddingReferenceIdToPaymentRequest : Migration
+ {
+
+ protected override void Up(MigrationBuilder migrationBuilder)
+ {
+ migrationBuilder.AddColumn(
+ name: "ReferenceId",
+ table: "PaymentRequests",
+ type: "TEXT",
+ nullable: true);
+ migrationBuilder.Sql("""
+ CREATE UNIQUE INDEX IX_PaymentRequests_StoreDataId_ReferenceId
+ ON "PaymentRequests" ("StoreDataId", "ReferenceId")
+ WHERE "ReferenceId" IS NOT NULL;
+ """);
+ }
+
+ protected override void Down(MigrationBuilder migrationBuilder)
+ {
+ migrationBuilder.DropColumn(
+ name: "ReferenceId",
+ table: "PaymentRequests");
+ }
+ }
+}
diff --git a/BTCPayServer.Data/Migrations/ApplicationDbContextModelSnapshot.cs b/BTCPayServer.Data/Migrations/ApplicationDbContextModelSnapshot.cs
index 00fa37212..45746b1c2 100644
--- a/BTCPayServer.Data/Migrations/ApplicationDbContextModelSnapshot.cs
+++ b/BTCPayServer.Data/Migrations/ApplicationDbContextModelSnapshot.cs
@@ -1,4 +1,4 @@
-//
+//
using System;
using System.Collections.Generic;
using BTCPayServer.Data;
@@ -544,6 +544,9 @@ namespace BTCPayServer.Migrations
b.Property("Expiry")
.HasColumnType("timestamp with time zone");
+ b.Property("ReferenceId")
+ .HasColumnType("text");
+
b.Property("Status")
.IsRequired()
.HasColumnType("text");
diff --git a/BTCPayServer.Tests/GreenfieldAPITests.cs b/BTCPayServer.Tests/GreenfieldAPITests.cs
index e70a17210..f559d91a3 100644
--- a/BTCPayServer.Tests/GreenfieldAPITests.cs
+++ b/BTCPayServer.Tests/GreenfieldAPITests.cs
@@ -2048,7 +2048,7 @@ namespace BTCPayServer.Tests
new() { Title = "A", Currency = "helloinvalid", Amount = 1 });
});
var newPaymentRequest = await client.CreatePaymentRequest(user.StoreId,
- new() { Title = "A", Currency = "USD", Amount = 1 });
+ new() { Title = "A", Currency = "USD", Amount = 1, ReferenceId = "1234"});
//list payment request
var paymentRequests = await viewOnly.GetPaymentRequests(user.StoreId);
@@ -2061,10 +2061,12 @@ namespace BTCPayServer.Tests
var paymentRequest = await viewOnly.GetPaymentRequest(user.StoreId, newPaymentRequest.Id);
Assert.Equal(newPaymentRequest.Title, paymentRequest.Title);
Assert.Equal(newPaymentRequest.StoreId, user.StoreId);
+ Assert.Equal(newPaymentRequest.ReferenceId, paymentRequest.ReferenceId);
//update payment request
var updateRequest = paymentRequest;
updateRequest.Title = "B";
+ updateRequest.ReferenceId = "EmperorNicolasGeneralRockstar";
await AssertHttpError(403, async () =>
{
await viewOnly.UpdatePaymentRequest(user.StoreId, paymentRequest.Id, updateRequest);
@@ -2072,6 +2074,7 @@ namespace BTCPayServer.Tests
await client.UpdatePaymentRequest(user.StoreId, paymentRequest.Id, updateRequest);
paymentRequest = await client.GetPaymentRequest(user.StoreId, newPaymentRequest.Id);
Assert.Equal(updateRequest.Title, paymentRequest.Title);
+ Assert.Equal(updateRequest.ReferenceId, paymentRequest.ReferenceId);
//archive payment request
await AssertHttpError(403, async () =>
diff --git a/BTCPayServer.Tests/PaymentRequestTests.cs b/BTCPayServer.Tests/PaymentRequestTests.cs
index 98fa378cd..2a7322881 100644
--- a/BTCPayServer.Tests/PaymentRequestTests.cs
+++ b/BTCPayServer.Tests/PaymentRequestTests.cs
@@ -43,12 +43,20 @@ namespace BTCPayServer.Tests
Currency = "BTC",
Amount = 1,
StoreId = user.StoreId,
- Description = "description"
+ Description = "description",
+ ReferenceId = "custom-id-1"
};
var id = Assert
.IsType(await paymentRequestController.EditPaymentRequest(null, request))
.RouteValues.Values.Last().ToString();
+ // Assert initial Title and ReferenceId
+ var repo = tester.PayTester.GetService();
+ var prData = await repo.FindPaymentRequest(id, user.UserId);
+ Assert.NotNull(prData);
+ Assert.Equal("original juice", prData.GetBlob().Title);
+ Assert.Equal("custom-id-1", prData.ReferenceId);
+
paymentRequestController.HttpContext.SetPaymentRequestData(new PaymentRequestData { Id = id, StoreDataId = request.StoreId });
// Permission guard for guests editing
@@ -56,8 +64,15 @@ namespace BTCPayServer.Tests
.IsType(await guestpaymentRequestController.EditPaymentRequest(user.StoreId, id));
request.Title = "update";
+ request.ReferenceId = "custom-id-2";
Assert.IsType(await paymentRequestController.EditPaymentRequest(id, request));
+ // Assert updated Title and ReferenceId
+ prData = await repo.FindPaymentRequest(id, user.UserId);
+ Assert.NotNull(prData);
+ Assert.Equal("update", prData.GetBlob().Title);
+ Assert.Equal("custom-id-2", prData.ReferenceId);
+
Assert.Equal(request.Title,
Assert.IsType(Assert
.IsType(await paymentRequestController.ViewPaymentRequest(id)).Model).Title);
diff --git a/BTCPayServer/Controllers/GreenField/GreenfieldPaymentRequestsController.cs b/BTCPayServer/Controllers/GreenField/GreenfieldPaymentRequestsController.cs
index 102493cae..b61deb1b6 100644
--- a/BTCPayServer/Controllers/GreenField/GreenfieldPaymentRequestsController.cs
+++ b/BTCPayServer/Controllers/GreenField/GreenfieldPaymentRequestsController.cs
@@ -205,7 +205,7 @@ namespace BTCPayServer.Controllers.Greenfield
pr = new PaymentRequestData()
{
StoreDataId = storeId,
- Status = Client.Models.PaymentRequestStatus.Pending,
+ Status = PaymentRequestStatus.Pending,
Created = DateTimeOffset.UtcNow,
Amount = request.Amount,
Currency = request.Currency ?? StoreData.GetStoreBlob().DefaultCurrency,
@@ -213,17 +213,19 @@ namespace BTCPayServer.Controllers.Greenfield
};
}
+ pr.ReferenceId = string.IsNullOrEmpty(request.ReferenceId) ? null : request.ReferenceId;
+
if (!ModelState.IsValid)
return this.CreateValidationError(ModelState);
var blob = pr.GetBlob();
pr.SetBlob(new()
{
+ Title = request.Title,
AllowCustomPaymentAmounts = request.AllowCustomPaymentAmounts,
Description = request.Description,
Email = request.Email,
FormId = request.FormId,
- Title = request.Title,
FormResponse = blob.FormId != request.FormId ? null : blob.FormResponse
});
pr = await _paymentRequestRepository.CreateOrUpdatePaymentRequest(pr);
@@ -251,6 +253,7 @@ namespace BTCPayServer.Controllers.Greenfield
Title = blob.Title,
ExpiryDate = data.Expiry,
Email = blob.Email,
+ ReferenceId = data.ReferenceId,
AllowCustomPaymentAmounts = blob.AllowCustomPaymentAmounts,
FormResponse = blob.FormResponse,
FormId = blob.FormId
diff --git a/BTCPayServer/Controllers/UIInvoiceController.cs b/BTCPayServer/Controllers/UIInvoiceController.cs
index 30dd5d40f..80d39df45 100644
--- a/BTCPayServer/Controllers/UIInvoiceController.cs
+++ b/BTCPayServer/Controllers/UIInvoiceController.cs
@@ -145,7 +145,7 @@ namespace BTCPayServer.Controllers
amount = amountDue;
var redirectUrl = _linkGenerator.PaymentRequestLink(id, request.Scheme, request.Host, request.PathBase);
- JObject invoiceMetadata = prData.GetBlob()?.FormResponse ?? new JObject();
+ JObject invoiceMetadata = prBlob.FormResponse ?? new JObject();
invoiceMetadata.Merge(new InvoiceMetadata
{
OrderId = PaymentRequestRepository.GetOrderIdForPaymentRequest(id),
@@ -163,7 +163,8 @@ namespace BTCPayServer.Controllers
Checkout = { RedirectURL = redirectUrl },
Receipt = new InvoiceDataBase.ReceiptOptions { Enabled = false }
};
-
+ if (prData.ReferenceId is not null or "")
+ invoiceRequest.AdditionalSearchTerms = [prData.ReferenceId];
var additionalTags = new List { PaymentRequestRepository.GetInternalTag(id) };
return await CreateInvoiceCoreRaw(invoiceRequest, storeData, request.GetAbsoluteRoot(), additionalTags, cancellationToken);
}
diff --git a/BTCPayServer/Controllers/UIPaymentRequestController.cs b/BTCPayServer/Controllers/UIPaymentRequestController.cs
index 192347685..42a406910 100644
--- a/BTCPayServer/Controllers/UIPaymentRequestController.cs
+++ b/BTCPayServer/Controllers/UIPaymentRequestController.cs
@@ -99,7 +99,8 @@ namespace BTCPayServer.Controllers
Skip = model.Skip,
Count = model.Count,
Status = fs.GetFilterArray("status")?.Select(s => Enum.Parse(s, true)).ToArray(),
- IncludeArchived = fs.GetFilterBool("includearchived") ?? false
+ IncludeArchived = fs.GetFilterBool("includearchived") ?? false,
+ SearchText = model.SearchText
});
model.Search = fs;
@@ -206,6 +207,7 @@ namespace BTCPayServer.Controllers
data.Amount = viewModel.Amount;
data.Currency = viewModel.Currency ?? store.GetStoreBlob().DefaultCurrency;
data.Expiry = viewModel.ExpiryDate?.ToUniversalTime();
+ data.ReferenceId = viewModel.ReferenceId;
blob.AllowCustomPaymentAmounts = viewModel.AllowCustomPaymentAmounts;
blob.FormId = viewModel.FormId;
diff --git a/BTCPayServer/HostedServices/Webhooks/PaymentRequestWebhookDeliveryRequest.cs b/BTCPayServer/HostedServices/Webhooks/PaymentRequestWebhookDeliveryRequest.cs
index 7130442d2..24c7d7fc1 100644
--- a/BTCPayServer/HostedServices/Webhooks/PaymentRequestWebhookDeliveryRequest.cs
+++ b/BTCPayServer/HostedServices/Webhooks/PaymentRequestWebhookDeliveryRequest.cs
@@ -47,7 +47,8 @@ public class PaymentRequestWebhookDeliveryRequest : WebhookSender.WebhookDeliver
.Replace("{PaymentRequest.Currency}", data.Currency)
.Replace("{PaymentRequest.Title}", blob.Title)
.Replace("{PaymentRequest.Description}", blob.Description)
- .Replace("{PaymentRequest.Status}", data.Status.ToString());
+ .Replace("{PaymentRequest.ReferenceId}", data.ReferenceId)
+ .Replace("{PaymentRequest.Status}", _evt.Data.Status.ToString());
res = InterpolateJsonField(res, "PaymentRequest.FormResponse", blob.FormResponse);
return res;
diff --git a/BTCPayServer/HostedServices/Webhooks/PaymentRequestWebhookProvider.cs b/BTCPayServer/HostedServices/Webhooks/PaymentRequestWebhookProvider.cs
index c018b3ea4..4df461544 100644
--- a/BTCPayServer/HostedServices/Webhooks/PaymentRequestWebhookProvider.cs
+++ b/BTCPayServer/HostedServices/Webhooks/PaymentRequestWebhookProvider.cs
@@ -22,6 +22,7 @@ public class PaymentRequestWebhookProvider: WebhookProvider
{WebhookEventType.PaymentRequestUpdated, "Payment Request - Updated"},
{WebhookEventType.PaymentRequestArchived, "Payment Request - Archived"},
{WebhookEventType.PaymentRequestStatusChanged, "Payment Request - Status Changed"},
+ {WebhookEventType.PaymentRequestCompleted, "Payment Request - Completed"},
};
}
@@ -42,6 +43,7 @@ public class PaymentRequestWebhookProvider: WebhookProvider
PaymentRequestEvent.Updated => new WebhookPaymentRequestEvent(WebhookEventType.PaymentRequestUpdated, evt.Data.StoreDataId),
PaymentRequestEvent.Archived => new WebhookPaymentRequestEvent(WebhookEventType.PaymentRequestArchived, evt.Data.StoreDataId),
PaymentRequestEvent.StatusChanged => new WebhookPaymentRequestEvent(WebhookEventType.PaymentRequestStatusChanged, evt.Data.StoreDataId),
+ PaymentRequestEvent.Completed => new WebhookPaymentRequestEvent(WebhookEventType.PaymentRequestCompleted, evt.Data.StoreDataId),
_ => null
};
}
diff --git a/BTCPayServer/Models/PaymentRequestViewModels/ListPaymentRequestsViewModel.cs b/BTCPayServer/Models/PaymentRequestViewModels/ListPaymentRequestsViewModel.cs
index c1c000c44..0108c530d 100644
--- a/BTCPayServer/Models/PaymentRequestViewModels/ListPaymentRequestsViewModel.cs
+++ b/BTCPayServer/Models/PaymentRequestViewModels/ListPaymentRequestsViewModel.cs
@@ -48,6 +48,7 @@ namespace BTCPayServer.Models.PaymentRequestViewModels
Description = blob.Description;
ExpiryDate = data.Expiry?.UtcDateTime;
Email = blob.Email;
+ ReferenceId = data.ReferenceId;
AllowCustomPaymentAmounts = blob.AllowCustomPaymentAmounts;
FormResponse = blob.FormResponse is null
? null
@@ -84,6 +85,9 @@ namespace BTCPayServer.Models.PaymentRequestViewModels
[MailboxAddress]
public string Email { get; set; }
+ [Display(Name = "Reference Id")]
+ public string ReferenceId { get; set; }
+
[Display(Name = "Allow payee to create invoices with custom amounts")]
public bool AllowCustomPaymentAmounts { get; set; }
@@ -106,6 +110,7 @@ namespace BTCPayServer.Models.PaymentRequestViewModels
Description = blob.Description;
ExpiryDate = data.Expiry?.UtcDateTime;
Email = blob.Email;
+ ReferenceId = data.ReferenceId;
AllowCustomPaymentAmounts = blob.AllowCustomPaymentAmounts;
switch (data.Status)
{
@@ -127,6 +132,7 @@ namespace BTCPayServer.Models.PaymentRequestViewModels
}
}
public StoreBrandingViewModel StoreBranding { get; set; }
+ public string ReferenceId { get; set; }
public bool AllowCustomPaymentAmounts { get; set; }
public string Email { get; set; }
public string Status { get; set; }
@@ -147,11 +153,11 @@ namespace BTCPayServer.Models.PaymentRequestViewModels
#nullable enable
public class InvoiceList : List
{
- static HashSet stateAllowedToDisplay = new HashSet
- {
- new InvoiceState(InvoiceStatus.New, InvoiceExceptionStatus.None),
- new InvoiceState(InvoiceStatus.New, InvoiceExceptionStatus.PaidPartial),
- };
+ private static HashSet stateAllowedToDisplay =
+ [
+ new(InvoiceStatus.New, InvoiceExceptionStatus.None),
+ new(InvoiceStatus.New, InvoiceExceptionStatus.PaidPartial)
+ ];
public InvoiceList()
{
@@ -195,7 +201,7 @@ namespace BTCPayServer.Models.PaymentRequestViewModels
public class PaymentRequestInvoicePayment
{
- public static List
+ public static List
GetViewModels(
InvoiceEntity invoice,
DisplayFormatter displayFormatter,
@@ -215,7 +221,7 @@ namespace BTCPayServer.Models.PaymentRequestViewModels
string link = paymentMethodId is null ? null : txLinkProvider.GetTransactionLink(paymentMethodId, txId);
- return new ViewPaymentRequestViewModel.PaymentRequestInvoicePayment
+ return new PaymentRequestInvoicePayment
{
Amount = paymentEntity.PaidAmount.Gross,
Paid = paymentEntity.InvoicePaidAmount.Net,
diff --git a/BTCPayServer/Services/CallbackGenerator.cs b/BTCPayServer/Services/CallbackGenerator.cs
index 015af6280..3b0bb9f71 100644
--- a/BTCPayServer/Services/CallbackGenerator.cs
+++ b/BTCPayServer/Services/CallbackGenerator.cs
@@ -92,5 +92,29 @@ namespace BTCPayServer.Services
pathBase: request.PathBase
) ?? throw Bug();
}
+
+ public string PaymentRequestByIdLink(string payReqId, HttpRequest request)
+ {
+ return LinkGenerator.GetUriByAction(
+ action: nameof(UIPaymentRequestController.ViewPaymentRequest),
+ controller: "UIPaymentRequest",
+ values: new { payReqId },
+ scheme: request.Scheme,
+ host: request.Host,
+ pathBase: request.PathBase
+ ) ?? throw Bug();
+ }
+
+ public string PaymentRequestListLink(string storeId, HttpRequest request)
+ {
+ return LinkGenerator.GetUriByAction(
+ action: nameof(UIPaymentRequestController.GetPaymentRequests),
+ controller: "UIPaymentRequest",
+ values: new { storeId },
+ scheme: request.Scheme,
+ host: request.Host,
+ pathBase: request.PathBase
+ ) ?? throw Bug();
+ }
}
}
diff --git a/BTCPayServer/Services/PaymentRequests/PaymentRequestRepository.cs b/BTCPayServer/Services/PaymentRequests/PaymentRequestRepository.cs
index a20271c82..652235c79 100644
--- a/BTCPayServer/Services/PaymentRequests/PaymentRequestRepository.cs
+++ b/BTCPayServer/Services/PaymentRequests/PaymentRequestRepository.cs
@@ -2,10 +2,12 @@ using System;
using System.Linq;
using System.Threading;
using System.Threading.Tasks;
+using BTCPayServer.Client.Models;
using BTCPayServer.Data;
using BTCPayServer.Services.Invoices;
using BTCPayServer.Services.Stores;
using Microsoft.EntityFrameworkCore;
+using Newtonsoft.Json.Linq;
namespace BTCPayServer.Services.PaymentRequests
{
@@ -15,6 +17,7 @@ namespace BTCPayServer.Services.PaymentRequests
public const string Updated = nameof(Updated);
public const string Archived = nameof(Archived);
public const string StatusChanged = nameof(StatusChanged);
+ public const string Completed = nameof(Completed);
public PaymentRequestData Data { get; set; }
public string Type { get; set; }
}
@@ -99,9 +102,7 @@ namespace BTCPayServer.Services.PaymentRequests
{
await using var context = _ContextFactory.CreateContext();
var paymentRequestData = await context.FindAsync(paymentRequestId);
- if (paymentRequestData == null)
- return;
- if( paymentRequestData.Status == status)
+ if (paymentRequestData == null || paymentRequestData.Status == status)
return;
paymentRequestData.Status = status;
@@ -112,6 +113,15 @@ namespace BTCPayServer.Services.PaymentRequests
Data = paymentRequestData,
Type = PaymentRequestEvent.StatusChanged
});
+
+ if (status == PaymentRequestStatus.Completed)
+ {
+ _eventAggregator.Publish(new PaymentRequestEvent()
+ {
+ Data = paymentRequestData,
+ Type = PaymentRequestEvent.Completed
+ });
+ }
}
public async Task GetExpirablePaymentRequests(CancellationToken cancellationToken = default)
{
@@ -126,48 +136,43 @@ namespace BTCPayServer.Services.PaymentRequests
}
public async Task FindPaymentRequests(PaymentRequestQuery query, CancellationToken cancellationToken = default)
{
- using var context = _ContextFactory.CreateContext();
- var queryable = context.PaymentRequests.Include(data => data.StoreData).AsQueryable();
+ await using var context = _ContextFactory.CreateContext();
+ IQueryable queryable = context.PaymentRequests.AsQueryable();
+
+ if (!string.IsNullOrEmpty(query.StoreId))
+ queryable = queryable.Where(data => data.StoreDataId == query.StoreId);
+
+ if (!string.IsNullOrEmpty(query.SearchText))
+ {
+ if (string.IsNullOrEmpty(query.StoreId))
+ throw new InvalidOperationException("PaymentRequestQuery.StoreId should be specified");
+ // We are repeating the StoreId on purpose here, so Postgres can use the index
+ queryable = context.PaymentRequests.Where(p => (p.StoreDataId == query.StoreId && p.ReferenceId == query.SearchText) || p.Id == query.SearchText);
+ }
+
+ queryable = queryable.Include(data => data.StoreData);
if (!query.IncludeArchived)
- {
queryable = queryable.Where(data => !data.Archived);
- }
- if (!string.IsNullOrEmpty(query.StoreId))
- {
- queryable = queryable.Where(data =>
- data.StoreDataId == query.StoreId);
- }
if (query.Status != null && query.Status.Any())
- {
- queryable = queryable.Where(data =>
- query.Status.Contains(data.Status));
- }
+ queryable = queryable.Where(data => query.Status.Contains(data.Status));
if (query.Ids != null && query.Ids.Any())
- {
- queryable = queryable.Where(data =>
- query.Ids.Contains(data.Id));
- }
+ queryable = queryable.Where(data => query.Ids.Contains(data.Id));
if (!string.IsNullOrEmpty(query.UserId))
- {
- queryable = queryable.Where(i =>
- i.StoreData != null && i.StoreData.UserStores.Any(u => u.ApplicationUserId == query.UserId));
- }
+ queryable = queryable.Where(data =>
+ data.StoreData.UserStores.Any(u => u.ApplicationUserId == query.UserId));
queryable = queryable.OrderByDescending(u => u.Created);
if (query.Skip.HasValue)
- {
queryable = queryable.Skip(query.Skip.Value);
- }
if (query.Count.HasValue)
- {
queryable = queryable.Take(query.Count.Value);
- }
+
var items = await queryable.ToArrayAsync(cancellationToken);
return items;
}
@@ -221,5 +226,6 @@ namespace BTCPayServer.Services.PaymentRequests
public int? Skip { get; set; }
public int? Count { get; set; }
public string[] Ids { get; set; }
+ public string SearchText { get; set; }
}
}
diff --git a/BTCPayServer/Views/UIPaymentRequest/EditPaymentRequest.cshtml b/BTCPayServer/Views/UIPaymentRequest/EditPaymentRequest.cshtml
index 0c56a10a7..591236f24 100644
--- a/BTCPayServer/Views/UIPaymentRequest/EditPaymentRequest.cshtml
+++ b/BTCPayServer/Views/UIPaymentRequest/EditPaymentRequest.cshtml
@@ -1,6 +1,7 @@
@using BTCPayServer.Services.PaymentRequests
@using System.Globalization
@using BTCPayServer.Client
+@using BTCPayServer.Controllers
@using BTCPayServer.Forms
@using BTCPayServer.TagHelpers
@using Microsoft.AspNetCore.Mvc.TagHelpers
@@ -82,6 +83,11 @@
+
+
+
+
+
@@ -99,7 +105,8 @@
"]" class="form-control" />
- @ViewLocalizer["This will send notification mails to the recipient, as configured by the {0}.", Html.ActionLink(StringLocalizer["email rules"], "StoreEmails", "UIStores", new { storeId = Model.StoreId })]
+ @ViewLocalizer["This will send notification mails to the recipient, as configured by the {0}.",
+ Html.ActionLink(StringLocalizer["email rules"], nameof(UIStoresController.StoreEmailRulesList), "UIStores", new { storeId = Model.StoreId })]
@if (Model.HasEmailRules is not true)
{