Bugfix: Could not find an order by OrderId after it's OrderId was changed through the API

This commit is contained in:
Wouter Samaey
2022-03-03 15:15:10 +01:00
committed by Andrew Camilleri
parent c7969476b0
commit 3b4d06a1e5
2 changed files with 45 additions and 4 deletions

View File

@@ -1193,12 +1193,13 @@ namespace BTCPayServer.Tests
new CreateInvoiceRequest() { Currency = "helloinvalid", Amount = 1 });
});
await user.RegisterDerivationSchemeAsync("BTC");
string origOrderId = "testOrder";
var newInvoice = await client.CreateInvoice(user.StoreId,
new CreateInvoiceRequest()
{
Currency = "USD",
Amount = 1,
Metadata = JObject.Parse("{\"itemCode\": \"testitem\", \"orderId\": \"testOrder\"}"),
Metadata = JObject.Parse($"{{\"itemCode\": \"testitem\", \"orderId\": \"{origOrderId}\"}}"),
Checkout = new CreateInvoiceRequest.CheckoutOptions()
{
RedirectAutomatically = true,
@@ -1319,6 +1320,8 @@ namespace BTCPayServer.Tests
newInvoice = await client.GetInvoice(user.StoreId, newInvoice.Id);
const string newOrderId = "UPDATED-ORDER-ID";
JObject metadataForUpdate = JObject.Parse($"{{\"orderId\": \"{newOrderId}\", \"itemCode\": \"updated\", newstuff: [1,2,3,4,5]}}");
Assert.Contains(InvoiceStatus.Settled, newInvoice.AvailableStatusesForManualMarking);
Assert.DoesNotContain(InvoiceStatus.Invalid, newInvoice.AvailableStatusesForManualMarking);
await AssertHttpError(403, async () =>
@@ -1326,23 +1329,36 @@ namespace BTCPayServer.Tests
await viewOnly.UpdateInvoice(user.StoreId, invoice.Id,
new UpdateInvoiceRequest()
{
Metadata = JObject.Parse("{\"itemCode\": \"updated\", newstuff: [1,2,3,4,5]}")
Metadata = metadataForUpdate
});
});
invoice = await client.UpdateInvoice(user.StoreId, invoice.Id,
new UpdateInvoiceRequest()
{
Metadata = JObject.Parse("{\"itemCode\": \"updated\", newstuff: [1,2,3,4,5]}")
Metadata = metadataForUpdate
});
Assert.Equal(newOrderId, invoice.Metadata["orderId"].Value<string>());
Assert.Equal("updated", invoice.Metadata["itemCode"].Value<string>());
Assert.Equal(15, ((JArray)invoice.Metadata["newstuff"]).Values<int>().Sum());
//also test the the metadata actually got saved
invoice = await client.GetInvoice(user.StoreId, invoice.Id);
Assert.Equal(newOrderId, invoice.Metadata["orderId"].Value<string>());
Assert.Equal("updated", invoice.Metadata["itemCode"].Value<string>());
Assert.Equal(15, ((JArray)invoice.Metadata["newstuff"]).Values<int>().Sum());
// test if we can find the updated invoice using the new orderId
var invoicesWithOrderId = await client.GetInvoices(user.StoreId, new[] { newOrderId });
Assert.NotNull(invoicesWithOrderId);
Assert.Single(invoicesWithOrderId);
Assert.Equal(invoice.Id, invoicesWithOrderId.First().Id);
// test if the old orderId does not yield any results anymore
var invoicesWithOldOrderId = await client.GetInvoices(user.StoreId, new[] { origOrderId });
Assert.NotNull(invoicesWithOldOrderId);
Assert.Empty(invoicesWithOldOrderId);
//archive
await AssertHttpError(403, async () =>
{

View File

@@ -400,6 +400,14 @@ namespace BTCPayServer.Services.Invoices
context.AddRange(filteredTerms);
}
public static void RemoveFromTextSearch(ApplicationDbContext context, InvoiceData invoice,
string term)
{
var query = context.InvoiceSearches.AsQueryable();
var filteredQuery = query.Where( st => st.InvoiceDataId.Equals(invoice.Id) && st.Value.Equals(term));
context.InvoiceSearches.RemoveRange(filteredQuery);
}
public async Task UpdateInvoiceStatus(string invoiceId, InvoiceState invoiceState)
{
using var context = _applicationDbContextFactory.CreateContext();
@@ -462,7 +470,24 @@ namespace BTCPayServer.Services.Invoices
StringComparison.InvariantCultureIgnoreCase)))
return null;
var blob = invoiceData.GetBlob(_btcPayNetworkProvider);
blob.Metadata = InvoiceMetadata.FromJObject(metadata);
var newMetadata = InvoiceMetadata.FromJObject(metadata);
var oldOrderId = blob.Metadata.OrderId;
var newOrderId = newMetadata.OrderId;
if (newOrderId != null)
{
// OrderId is saved in 2 places: (1) the invoice table and (2) in the metadata field. We are updating both for consistency.
invoiceData.OrderId = newOrderId;
if (oldOrderId != null && !newOrderId.Equals(oldOrderId, StringComparison.InvariantCulture))
{
RemoveFromTextSearch(context, invoiceData, oldOrderId);
}
AddToTextSearch(context, invoiceData, new[] { newOrderId });
}
blob.Metadata = newMetadata;
invoiceData.Blob = ToBytes(blob);
await context.SaveChangesAsync().ConfigureAwait(false);
return ToEntity(invoiceData);