using Baya.Domain.Entities.Booking; using Baya.Domain.Entities.Identity; using Baya.Domain.Entities.Messaging; using Baya.Domain.Entities.Payments; using Baya.Domain.Entities.Refunds; using Microsoft.EntityFrameworkCore; using Microsoft.EntityFrameworkCore.Metadata.Builders; namespace Baya.Infrastructure.Persistence.Configuration.RefundsConfig; /// /// refunds — 1:N per payment_transaction. The amount = fee_leg + payout_leg reconciliation /// is a DB CHECK (the "Σ refunded ≤ captured" invariant is a handler check under the booking refund lock, not a /// single-row constraint). ticket_id is a nullable FK to messaging.Tickets (b15 shipped the table; /// refinement-phase-6 added the constraint, ON DELETE NO ACTION). /// internal sealed class RefundConfig : IEntityTypeConfiguration { public void Configure(EntityTypeBuilder builder) { builder.ToTable("Refunds", "payments", t => t.HasCheckConstraint( "CK_Refunds_LegSplit", "[Amount] = [PlatformFeeRefundedIrr] + [NursePayoutRefundedIrr] " + "AND [Amount] >= 0 AND [PlatformFeeRefundedIrr] >= 0 AND [NursePayoutRefundedIrr] >= 0")); builder.Property(r => r.RefundChannel).HasMaxLength(20).IsRequired(); builder.Property(r => r.Status).HasMaxLength(20).IsRequired(); builder.Property(r => r.ReasonCategory).HasMaxLength(50); builder.Property(r => r.ReasonNotes).HasMaxLength(1000); builder.Property(r => r.AdminNotes).HasMaxLength(1000); builder.Property(r => r.RejectedReason).HasMaxLength(500); builder.Property(r => r.GatewayRefundReference).HasMaxLength(200); builder.Property(r => r.ExternalRevertReference).HasMaxLength(200); builder.Property(r => r.CancellationPolicyCode).HasMaxLength(50); builder.Property(r => r.RefundPercentage).HasPrecision(6, 4); builder.Property(r => r.RefundPercentageApplied).HasPrecision(5, 2); builder.HasIndex(r => r.PaymentTransactionId); builder.HasIndex(r => r.BookingId); builder.HasIndex(r => r.RequestedByCustomerId); builder.HasIndex(r => r.Status); builder.HasIndex(r => r.TicketId); builder.HasOne().WithMany().HasForeignKey(r => r.PaymentTransactionId).IsRequired(); builder.HasOne().WithMany().HasForeignKey(r => r.BookingId).IsRequired(); builder.HasOne().WithMany().HasForeignKey(r => r.RequestedByCustomerId).IsRequired(); // Forward-dep FK to the b15 tickets table (refinement-phase-6). Optional (nullable); NO ACTION so deleting // a ticket never cascades into money rows. builder.HasOne().WithMany().HasForeignKey(r => r.TicketId).OnDelete(DeleteBehavior.NoAction); builder.HasQueryFilter(r => r.DeletedAt == null); } }