mirror of
https://github.com/btcpayserver/btcpayserver.git
synced 2025-03-10 00:09:18 +01:00
Add SQL test for GetMonitoredInvoices
This commit is contained in:
parent
9d3f8672d9
commit
c97c9d4ece
4 changed files with 126 additions and 13 deletions
|
@ -5,6 +5,7 @@ using System.Linq;
|
||||||
using System.Threading.Tasks;
|
using System.Threading.Tasks;
|
||||||
using BTCPayServer.Abstractions.Models;
|
using BTCPayServer.Abstractions.Models;
|
||||||
using BTCPayServer.Data;
|
using BTCPayServer.Data;
|
||||||
|
using BTCPayServer.Services.Invoices;
|
||||||
using BTCPayServer.Tests.Logging;
|
using BTCPayServer.Tests.Logging;
|
||||||
using Dapper;
|
using Dapper;
|
||||||
using Microsoft.EntityFrameworkCore;
|
using Microsoft.EntityFrameworkCore;
|
||||||
|
@ -42,6 +43,13 @@ namespace BTCPayServer.Tests
|
||||||
}), _loggerFactory);
|
}), _loggerFactory);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public InvoiceRepository GetInvoiceRepository()
|
||||||
|
{
|
||||||
|
var logs = new BTCPayServer.Logging.Logs();
|
||||||
|
logs.Configure(_loggerFactory);
|
||||||
|
return new InvoiceRepository(CreateContextFactory(), new EventAggregator(logs));
|
||||||
|
}
|
||||||
|
|
||||||
public ApplicationDbContext CreateContext() => CreateContextFactory().CreateContext();
|
public ApplicationDbContext CreateContext() => CreateContextFactory().CreateContext();
|
||||||
|
|
||||||
public async Task MigrateAsync()
|
public async Task MigrateAsync()
|
||||||
|
@ -59,18 +67,21 @@ namespace BTCPayServer.Tests
|
||||||
await conn.ExecuteAsync($"CREATE DATABASE \"{dbname}\";");
|
await conn.ExecuteAsync($"CREATE DATABASE \"{dbname}\";");
|
||||||
}
|
}
|
||||||
|
|
||||||
public async Task MigrateUntil(string migration)
|
public async Task MigrateUntil(string migration = null)
|
||||||
{
|
{
|
||||||
using var ctx = CreateContext();
|
using var ctx = CreateContext();
|
||||||
var db = ctx.Database.GetDbConnection();
|
var db = ctx.Database.GetDbConnection();
|
||||||
await EnsureCreatedAsync();
|
await EnsureCreatedAsync();
|
||||||
var migrations = ctx.Database.GetMigrations().ToArray();
|
var migrations = ctx.Database.GetMigrations().ToArray();
|
||||||
var untilMigrationIdx = Array.IndexOf(migrations, migration);
|
if (migration is not null)
|
||||||
if (untilMigrationIdx == -1)
|
{
|
||||||
throw new InvalidOperationException($"Migration {migration} not found");
|
var untilMigrationIdx = Array.IndexOf(migrations, migration);
|
||||||
notAppliedMigrations = migrations[untilMigrationIdx..];
|
if (untilMigrationIdx == -1)
|
||||||
await db.ExecuteAsync("CREATE TABLE IF NOT EXISTS \"__EFMigrationsHistory\" (\"MigrationId\" TEXT, \"ProductVersion\" TEXT)");
|
throw new InvalidOperationException($"Migration {migration} not found");
|
||||||
await db.ExecuteAsync("INSERT INTO \"__EFMigrationsHistory\" VALUES (@migration, '8.0.0')", notAppliedMigrations.Select(m => new { migration = m }).ToArray());
|
notAppliedMigrations = migrations[untilMigrationIdx..];
|
||||||
|
await db.ExecuteAsync("CREATE TABLE IF NOT EXISTS \"__EFMigrationsHistory\" (\"MigrationId\" TEXT, \"ProductVersion\" TEXT)");
|
||||||
|
await db.ExecuteAsync("INSERT INTO \"__EFMigrationsHistory\" VALUES (@migration, '8.0.0')", notAppliedMigrations.Select(m => new { migration = m }).ToArray());
|
||||||
|
}
|
||||||
await ctx.Database.MigrateAsync();
|
await ctx.Database.MigrateAsync();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -3,7 +3,9 @@ using System.Threading.Tasks;
|
||||||
using BTCPayServer.Payments;
|
using BTCPayServer.Payments;
|
||||||
using Dapper;
|
using Dapper;
|
||||||
using Microsoft.EntityFrameworkCore;
|
using Microsoft.EntityFrameworkCore;
|
||||||
|
using NBitcoin;
|
||||||
using NBitcoin.Altcoins;
|
using NBitcoin.Altcoins;
|
||||||
|
using NBitpayClient;
|
||||||
using Newtonsoft.Json.Linq;
|
using Newtonsoft.Json.Linq;
|
||||||
using Xunit;
|
using Xunit;
|
||||||
using Xunit.Abstractions;
|
using Xunit.Abstractions;
|
||||||
|
@ -18,6 +20,110 @@ namespace BTCPayServer.Tests
|
||||||
{
|
{
|
||||||
}
|
}
|
||||||
|
|
||||||
|
[Fact]
|
||||||
|
public async Task CanQueryMonitoredInvoices()
|
||||||
|
{
|
||||||
|
var tester = CreateDBTester();
|
||||||
|
await tester.MigrateUntil();
|
||||||
|
var invoiceRepository = tester.GetInvoiceRepository();
|
||||||
|
using var ctx = tester.CreateContext();
|
||||||
|
var conn = ctx.Database.GetDbConnection();
|
||||||
|
|
||||||
|
async Task AddPrompt(string invoiceId, string paymentMethodId, bool activated = true)
|
||||||
|
{
|
||||||
|
JObject prompt = new JObject();
|
||||||
|
if (!activated)
|
||||||
|
prompt["inactive"] = true;
|
||||||
|
prompt["currency"] = "USD";
|
||||||
|
var query = """
|
||||||
|
UPDATE "Invoices" SET "Blob2" = jsonb_set('{"prompts": {}}'::JSONB || COALESCE("Blob2",'{}'), ARRAY['prompts','@paymentMethodId'], '@prompt'::JSONB)
|
||||||
|
WHERE "Id" = '@invoiceId'
|
||||||
|
""";
|
||||||
|
query = query.Replace("@paymentMethodId", paymentMethodId);
|
||||||
|
query = query.Replace("@prompt", prompt.ToString());
|
||||||
|
query = query.Replace("@invoiceId", invoiceId);
|
||||||
|
Assert.Equal(1, await conn.ExecuteAsync(query));
|
||||||
|
}
|
||||||
|
|
||||||
|
await conn.ExecuteAsync("""
|
||||||
|
INSERT INTO "Invoices" ("Id", "Created", "Status","Currency") VALUES
|
||||||
|
('BTCOnly', NOW(), 'New', 'USD'),
|
||||||
|
('LTCOnly', NOW(), 'New', 'USD'),
|
||||||
|
('LTCAndBTC', NOW(), 'New', 'USD'),
|
||||||
|
('LTCAndBTCLazy', NOW(), 'New', 'USD')
|
||||||
|
""");
|
||||||
|
foreach (var invoiceId in new string[] { "LTCOnly", "LTCAndBTCLazy", "LTCAndBTC" })
|
||||||
|
{
|
||||||
|
await AddPrompt(invoiceId, "LTC-CHAIN", true);
|
||||||
|
}
|
||||||
|
foreach (var invoiceId in new string[] { "BTCOnly", "LTCAndBTC" })
|
||||||
|
{
|
||||||
|
await AddPrompt(invoiceId, "BTC-CHAIN", true);
|
||||||
|
}
|
||||||
|
await AddPrompt("LTCAndBTCLazy", "BTC-CHAIN", false);
|
||||||
|
|
||||||
|
var btc = PaymentMethodId.Parse("BTC-CHAIN");
|
||||||
|
var ltc = PaymentMethodId.Parse("LTC-CHAIN");
|
||||||
|
var invoices = await invoiceRepository.GetMonitoredInvoices(btc);
|
||||||
|
Assert.Equal(2, invoices.Length);
|
||||||
|
foreach (var invoiceId in new[] { "BTCOnly", "LTCAndBTC" })
|
||||||
|
{
|
||||||
|
Assert.Contains(invoices, i => i.Id == invoiceId);
|
||||||
|
}
|
||||||
|
invoices = await invoiceRepository.GetMonitoredInvoices(btc, true);
|
||||||
|
Assert.Equal(3, invoices.Length);
|
||||||
|
foreach (var invoiceId in new[] { "BTCOnly", "LTCAndBTC", "LTCAndBTCLazy" })
|
||||||
|
{
|
||||||
|
Assert.Contains(invoices, i => i.Id == invoiceId);
|
||||||
|
}
|
||||||
|
|
||||||
|
invoices = await invoiceRepository.GetMonitoredInvoices(ltc);
|
||||||
|
Assert.Equal(3, invoices.Length);
|
||||||
|
foreach (var invoiceId in new[] { "LTCAndBTC", "LTCAndBTC", "LTCAndBTCLazy" })
|
||||||
|
{
|
||||||
|
Assert.Contains(invoices, i => i.Id == invoiceId);
|
||||||
|
}
|
||||||
|
|
||||||
|
await conn.ExecuteAsync("""
|
||||||
|
INSERT INTO "Payments" ("Id", "InvoiceDataId", "PaymentMethodId", "Status", "Blob2", "Created", "Amount", "Currency") VALUES
|
||||||
|
('1','LTCAndBTC', 'LTC-CHAIN', 'Processing', '{}'::JSONB, NOW(), 123, 'USD'),
|
||||||
|
('2','LTCAndBTC', 'BTC-CHAIN', 'Processing', '{}'::JSONB, NOW(), 123, 'USD'),
|
||||||
|
('3','LTCAndBTC', 'BTC-CHAIN', 'Processing', '{}'::JSONB, NOW(), 123, 'USD'),
|
||||||
|
('4','LTCAndBTC', 'BTC-CHAIN', 'Settled', '{}'::JSONB, NOW(), 123, 'USD');
|
||||||
|
|
||||||
|
INSERT INTO "AddressInvoices" ("InvoiceDataId", "Address", "PaymentMethodId") VALUES
|
||||||
|
('LTCAndBTC', 'BTC1', 'BTC-CHAIN'),
|
||||||
|
('LTCAndBTC', 'BTC2', 'BTC-CHAIN'),
|
||||||
|
('LTCAndBTC', 'LTC1', 'LTC-CHAIN');
|
||||||
|
""");
|
||||||
|
|
||||||
|
var invoice = Assert.Single(await invoiceRepository.GetMonitoredInvoices(ltc), i => i.Id == "LTCAndBTC");
|
||||||
|
var payment = Assert.Single(invoice.GetPayments(false));
|
||||||
|
Assert.Equal("1", payment.Id);
|
||||||
|
|
||||||
|
foreach (var includeNonActivated in new[] { true, false })
|
||||||
|
{
|
||||||
|
invoices = await invoiceRepository.GetMonitoredInvoices(btc, includeNonActivated);
|
||||||
|
invoice = Assert.Single(invoices, i => i.Id == "LTCAndBTC");
|
||||||
|
var payments = invoice.GetPayments(false);
|
||||||
|
Assert.Equal(3, payments.Count);
|
||||||
|
|
||||||
|
foreach (var paymentId in new[] { "2", "3", "4" })
|
||||||
|
{
|
||||||
|
Assert.Contains(payments, p => p.Id == paymentId);
|
||||||
|
}
|
||||||
|
Assert.Equal(2, invoice.Addresses.Count);
|
||||||
|
foreach (var addr in new[] { "BTC1", "BTC2" })
|
||||||
|
{
|
||||||
|
Assert.Contains(invoice.Addresses, p => p.Address == addr);
|
||||||
|
}
|
||||||
|
if (!includeNonActivated)
|
||||||
|
Assert.DoesNotContain(invoices, i => i.Id == "LTCAndBTCLazy");
|
||||||
|
else
|
||||||
|
Assert.Contains(invoices, i => i.Id == "LTCAndBTCLazy");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
[Fact]
|
[Fact]
|
||||||
public async Task CanMigrateInvoiceAddresses()
|
public async Task CanMigrateInvoiceAddresses()
|
||||||
{
|
{
|
||||||
|
|
|
@ -32,7 +32,7 @@ namespace BTCPayServer.Data
|
||||||
#nullable enable
|
#nullable enable
|
||||||
public static PayoutMethodId? GetClosestPayoutMethodId(this InvoiceData invoice, IEnumerable<PayoutMethodId> pmids)
|
public static PayoutMethodId? GetClosestPayoutMethodId(this InvoiceData invoice, IEnumerable<PayoutMethodId> pmids)
|
||||||
{
|
{
|
||||||
var paymentMethodIds = invoice.Payments.Select(o => o.GetPaymentMethodId()).ToArray();
|
var paymentMethodIds = invoice.Payments.Select(o => PaymentMethodId.Parse(o.PaymentMethodId)).ToArray();
|
||||||
if (paymentMethodIds.Length == 0)
|
if (paymentMethodIds.Length == 0)
|
||||||
paymentMethodIds = invoice.GetBlob().GetPaymentPrompts().Select(p => p.PaymentMethodId).ToArray();
|
paymentMethodIds = invoice.GetBlob().GetPaymentPrompts().Select(p => p.PaymentMethodId).ToArray();
|
||||||
return PaymentMethodId.GetSimilarities(pmids, paymentMethodIds)
|
return PaymentMethodId.GetSimilarities(pmids, paymentMethodIds)
|
||||||
|
|
|
@ -38,16 +38,12 @@ namespace BTCPayServer.Data
|
||||||
paymentData.Blob2 = JToken.FromObject(blob, InvoiceDataExtensions.DefaultSerializer).ToString(Newtonsoft.Json.Formatting.None);
|
paymentData.Blob2 = JToken.FromObject(blob, InvoiceDataExtensions.DefaultSerializer).ToString(Newtonsoft.Json.Formatting.None);
|
||||||
return paymentData;
|
return paymentData;
|
||||||
}
|
}
|
||||||
public static PaymentMethodId GetPaymentMethodId(this PaymentData paymentData)
|
|
||||||
{
|
|
||||||
return PaymentMethodId.Parse(paymentData.PaymentMethodId);
|
|
||||||
}
|
|
||||||
public static PaymentEntity GetBlob(this PaymentData paymentData)
|
public static PaymentEntity GetBlob(this PaymentData paymentData)
|
||||||
{
|
{
|
||||||
var entity = JToken.Parse(paymentData.Blob2).ToObject<PaymentEntity>(InvoiceDataExtensions.DefaultSerializer) ?? throw new FormatException($"Invalid {nameof(PaymentEntity)}");
|
var entity = JToken.Parse(paymentData.Blob2).ToObject<PaymentEntity>(InvoiceDataExtensions.DefaultSerializer) ?? throw new FormatException($"Invalid {nameof(PaymentEntity)}");
|
||||||
entity.Status = paymentData.Status!.Value;
|
entity.Status = paymentData.Status!.Value;
|
||||||
entity.Currency = paymentData.Currency;
|
entity.Currency = paymentData.Currency;
|
||||||
entity.PaymentMethodId = GetPaymentMethodId(paymentData);
|
entity.PaymentMethodId = PaymentMethodId.Parse(paymentData.PaymentMethodId);
|
||||||
entity.Value = paymentData.Amount!.Value;
|
entity.Value = paymentData.Amount!.Value;
|
||||||
entity.Id = paymentData.Id;
|
entity.Id = paymentData.Id;
|
||||||
entity.ReceivedTime = paymentData.Created!.Value;
|
entity.ReceivedTime = paymentData.Created!.Value;
|
||||||
|
|
Loading…
Add table
Reference in a new issue