diff --git a/BTCPayServer.Data/Data/InvoiceData.cs b/BTCPayServer.Data/Data/InvoiceData.cs index da99085e8..554a1827d 100644 --- a/BTCPayServer.Data/Data/InvoiceData.cs +++ b/BTCPayServer.Data/Data/InvoiceData.cs @@ -30,9 +30,6 @@ namespace BTCPayServer.Data public List PendingInvoices { get; set; } public List InvoiceSearchData { get; set; } public List Refunds { get; set; } - public string CurrentRefundId { get; set; } - [ForeignKey("Id,CurrentRefundId")] - public RefundData CurrentRefund { get; set; } internal static void OnModelCreating(ModelBuilder builder, DatabaseFacade databaseFacade) @@ -42,8 +39,6 @@ namespace BTCPayServer.Data .WithMany(a => a.Invoices).OnDelete(DeleteBehavior.Cascade); builder.Entity().HasIndex(o => o.StoreDataId); builder.Entity().HasIndex(o => o.OrderId); - builder.Entity() - .HasOne(o => o.CurrentRefund); builder.Entity().HasIndex(o => o.Created); if (databaseFacade.IsNpgsql()) diff --git a/BTCPayServer.Data/Data/RefundData.cs b/BTCPayServer.Data/Data/RefundData.cs index b8caf9cde..dafbe5bf9 100644 --- a/BTCPayServer.Data/Data/RefundData.cs +++ b/BTCPayServer.Data/Data/RefundData.cs @@ -13,7 +13,6 @@ namespace BTCPayServer.Data public PullPaymentData PullPaymentData { get; set; } public InvoiceData InvoiceData { get; set; } - internal static void OnModelCreating(ModelBuilder builder) { builder.Entity() diff --git a/BTCPayServer.Data/Migrations/20231121031609_removecurrentrefund.cs b/BTCPayServer.Data/Migrations/20231121031609_removecurrentrefund.cs new file mode 100644 index 000000000..956df0d34 --- /dev/null +++ b/BTCPayServer.Data/Migrations/20231121031609_removecurrentrefund.cs @@ -0,0 +1,36 @@ +using BTCPayServer.Data; +using Microsoft.EntityFrameworkCore; +using Microsoft.EntityFrameworkCore.Infrastructure; +using Microsoft.EntityFrameworkCore.Migrations; + +#nullable disable + +namespace BTCPayServer.Migrations +{ + [DbContext(typeof(ApplicationDbContext))] + [Migration("20231121031609_removecurrentrefund")] + public partial class removecurrentrefund : Migration + { + protected override void Up(MigrationBuilder migrationBuilder) + { + if (migrationBuilder.IsNpgsql()) + { + migrationBuilder.DropForeignKey( + name: "FK_Invoices_Refunds_Id_CurrentRefundId", + table: "Invoices"); + + migrationBuilder.DropIndex( + name: "IX_Invoices_Id_CurrentRefundId", + table: "Invoices"); + + migrationBuilder.DropColumn( + name: "CurrentRefundId", + table: "Invoices"); + } + } + + protected override void Down(MigrationBuilder migrationBuilder) + { + } + } +} diff --git a/BTCPayServer.Data/Migrations/ApplicationDbContextModelSnapshot.cs b/BTCPayServer.Data/Migrations/ApplicationDbContextModelSnapshot.cs index 5e7dd21b4..7ce34c053 100644 --- a/BTCPayServer.Data/Migrations/ApplicationDbContextModelSnapshot.cs +++ b/BTCPayServer.Data/Migrations/ApplicationDbContextModelSnapshot.cs @@ -287,9 +287,6 @@ namespace BTCPayServer.Migrations b.Property("Created") .HasColumnType("TEXT"); - b.Property("CurrentRefundId") - .HasColumnType("TEXT"); - b.Property("CustomerEmail") .HasColumnType("TEXT"); @@ -316,8 +313,6 @@ namespace BTCPayServer.Migrations b.HasIndex("StoreDataId"); - b.HasIndex("Id", "CurrentRefundId"); - b.ToTable("Invoices"); }); @@ -1251,12 +1246,6 @@ namespace BTCPayServer.Migrations .HasForeignKey("StoreDataId") .OnDelete(DeleteBehavior.Cascade); - b.HasOne("BTCPayServer.Data.RefundData", "CurrentRefund") - .WithMany() - .HasForeignKey("Id", "CurrentRefundId"); - - b.Navigation("CurrentRefund"); - b.Navigation("StoreData"); }); diff --git a/BTCPayServer/Components/StoreNumbers/StoreNumbers.cs b/BTCPayServer/Components/StoreNumbers/StoreNumbers.cs index 27f2627ab..5bf35bf27 100644 --- a/BTCPayServer/Components/StoreNumbers/StoreNumbers.cs +++ b/BTCPayServer/Components/StoreNumbers/StoreNumbers.cs @@ -55,7 +55,8 @@ public class StoreNumbers : ViewComponent .Where(p => p.PullPaymentData.StoreId == vm.Store.Id && !p.PullPaymentData.Archived && p.State == PayoutState.AwaitingApproval) .CountAsync(); vm.RefundsIssued = await ctx.Invoices - .Where(i => i.StoreData.Id == vm.Store.Id && !i.Archived && i.CurrentRefundId != null && i.Created >= offset) + .Where(i => i.StoreData.Id == vm.Store.Id && !i.Archived && i.Created >= offset) + .SelectMany(i => i.Refunds) .CountAsync(); return View(vm); diff --git a/BTCPayServer/Controllers/GreenField/GreenfieldInvoiceController.cs b/BTCPayServer/Controllers/GreenField/GreenfieldInvoiceController.cs index 865089773..50a8c11ac 100644 --- a/BTCPayServer/Controllers/GreenField/GreenfieldInvoiceController.cs +++ b/BTCPayServer/Controllers/GreenField/GreenfieldInvoiceController.cs @@ -515,7 +515,7 @@ namespace BTCPayServer.Controllers.Greenfield var ppId = await _pullPaymentService.CreatePullPayment(createPullPayment); await using var ctx = _dbContextFactory.CreateContext(); - (await ctx.Invoices.FindAsync(new[] { invoice.Id }, cancellationToken))!.CurrentRefundId = ppId; + ctx.Refunds.Add(new RefundData { InvoiceDataId = invoice.Id, @@ -524,7 +524,6 @@ namespace BTCPayServer.Controllers.Greenfield await ctx.SaveChangesAsync(cancellationToken); var pp = await _pullPaymentService.GetPullPayment(ppId, false); - return this.Ok(CreatePullPaymentData(pp)); } diff --git a/BTCPayServer/Controllers/UIInvoiceController.UI.cs b/BTCPayServer/Controllers/UIInvoiceController.UI.cs index 801dbb0d8..6f2eb46dc 100644 --- a/BTCPayServer/Controllers/UIInvoiceController.UI.cs +++ b/BTCPayServer/Controllers/UIInvoiceController.UI.cs @@ -288,19 +288,19 @@ namespace BTCPayServer.Controllers await using var ctx = _dbContextFactory.CreateContext(); ctx.ChangeTracker.QueryTrackingBehavior = QueryTrackingBehavior.NoTracking; var invoice = await ctx.Invoices.Include(i => i.Payments) - .Include(i => i.CurrentRefund) + .Include(i => i.Refunds).ThenInclude(i => i.PullPaymentData) .Include(i => i.StoreData) .ThenInclude(data => data.UserStores) - .Include(i => i.CurrentRefund.PullPaymentData) .Where(i => i.Id == invoiceId) .FirstOrDefaultAsync(cancellationToken); if (invoice is null) return NotFound(); - if (invoice.CurrentRefund?.PullPaymentDataId is null && GetUserId() is null) + var currentRefund = invoice.Refunds.OrderByDescending(r => r.PullPaymentData.StartDate).FirstOrDefault(); + if (currentRefund?.PullPaymentDataId is null && GetUserId() is null) return NotFound(); if (!invoice.GetInvoiceState().CanRefund()) return NotFound(); - if (invoice.CurrentRefund?.PullPaymentDataId is string ppId && !invoice.CurrentRefund.PullPaymentData.Archived) + if (currentRefund?.PullPaymentDataId is string ppId && !currentRefund.PullPaymentData.Archived) { // TODO: Having dedicated UI later on return RedirectToAction(nameof(UIPullPaymentController.ViewPullPayment), @@ -550,7 +550,6 @@ namespace BTCPayServer.Controllers Html = "Refund successfully created!
Share the link to this page with a customer.
The customer needs to enter their address and claim the refund.
Once a customer claims the refund, you will get a notification and would need to approve and initiate it from your Store > Payouts.", Severity = StatusMessageModel.StatusSeverity.Success }); - (await ctx.Invoices.FindAsync(new[] { invoice.Id }, cancellationToken))!.CurrentRefundId = ppId; ctx.Refunds.Add(new RefundData { InvoiceDataId = invoice.Id, diff --git a/BTCPayServer/Hosting/ToPostgresMigrationStartupTask.cs b/BTCPayServer/Hosting/ToPostgresMigrationStartupTask.cs index 23da2fd43..4d63c7ef4 100644 --- a/BTCPayServer/Hosting/ToPostgresMigrationStartupTask.cs +++ b/BTCPayServer/Hosting/ToPostgresMigrationStartupTask.cs @@ -233,9 +233,6 @@ namespace BTCPayServer.Hosting var rows = await query.ToListAsync(); foreach (var row in rows) { - // There is as circular deps between invoice and refund. - if (row is InvoiceData id) - id.CurrentRefundId = null; foreach (var prop in datetimeProperties) { var v = (DateTime)prop.GetValue(row)!; @@ -262,10 +259,6 @@ namespace BTCPayServer.Hosting await postgresContext.SaveChangesAsync(); postgresContext.ChangeTracker.Clear(); } - foreach (var invoice in otherContext.Invoices.AsNoTracking().Where(i => i.CurrentRefundId != null)) - { - postgresContext.Entry(invoice).State = EntityState.Modified; - } await postgresContext.SaveChangesAsync(); postgresContext.ChangeTracker.Clear(); await UpdateSequenceInvoiceSearch(postgresContext);