mirror of
https://github.com/aljazceru/btcpayserver.git
synced 2026-02-01 20:34:38 +01:00
146 lines
4.5 KiB
C#
146 lines
4.5 KiB
C#
#nullable enable
|
|
using System;
|
|
using System.ComponentModel.DataAnnotations;
|
|
using System.ComponentModel.DataAnnotations.Schema;
|
|
using BTCPayServer.Abstractions;
|
|
using Microsoft.AspNetCore.WebUtilities;
|
|
using Microsoft.EntityFrameworkCore;
|
|
using Microsoft.EntityFrameworkCore.Infrastructure;
|
|
|
|
namespace BTCPayServer.Data.Subscriptions;
|
|
|
|
[Table("subs_plan_checkouts")]
|
|
public class PlanCheckoutData : BaseEntityData
|
|
{
|
|
public PlanCheckoutData()
|
|
{
|
|
|
|
}
|
|
|
|
public PlanCheckoutData(SubscriberData subscriber, PlanData? plan = null)
|
|
{
|
|
plan ??= subscriber.Plan;
|
|
NewSubscriber = false;
|
|
Subscriber = subscriber;
|
|
SubscriberId = subscriber.Id;
|
|
Plan = plan;
|
|
PlanId = plan.Id;
|
|
}
|
|
[Key]
|
|
[Column("id")]
|
|
public string Id { get; set; } = null!;
|
|
|
|
[Column("invoice_id")]
|
|
public string? InvoiceId { get; set; }
|
|
|
|
[ForeignKey(nameof(InvoiceId))]
|
|
public InvoiceData? Invoice { get; set; }
|
|
|
|
[Column("success_redirect_url")]
|
|
public string? SuccessRedirectUrl { get; set; }
|
|
|
|
[Column("is_trial")]
|
|
public bool IsTrial { get; set; }
|
|
|
|
[Required]
|
|
[Column("plan_id")]
|
|
public string PlanId { get; set; } = null!;
|
|
|
|
[ForeignKey(nameof(PlanId))]
|
|
public PlanData Plan { get; set; } = null!;
|
|
|
|
[Column("new_subscriber")]
|
|
public bool NewSubscriber { get; set; }
|
|
|
|
/// <summary>
|
|
/// Internal ID of the subscriber, do not expose outside, only use for querying.
|
|
/// </summary>
|
|
[Column("subscriber_id")]
|
|
public long? SubscriberId { get; set; }
|
|
|
|
[ForeignKey(nameof(SubscriberId))]
|
|
public SubscriberData? Subscriber { get; set; }
|
|
|
|
[Column("invoice_metadata", TypeName = "jsonb")]
|
|
public string InvoiceMetadata { get; set; } = "{}";
|
|
|
|
[Column("new_subscriber_metadata", TypeName = "jsonb")]
|
|
public string NewSubscriberMetadata { get; set; } = "{}";
|
|
|
|
[Column("test_account")]
|
|
public bool TestAccount { get; set; }
|
|
|
|
[Column("credited")]
|
|
public decimal Credited { get; set; } = 0m;
|
|
|
|
[Column("plan_started")]
|
|
public bool PlanStarted { get; set; }
|
|
|
|
[Column("refund_amount")]
|
|
public decimal? RefundAmount { get; set; }
|
|
|
|
[Column("on_pay")]
|
|
public OnPayBehavior OnPay { get; set; }
|
|
|
|
[Required]
|
|
[Column("base_url", TypeName = "text")]
|
|
public RequestBaseUrl BaseUrl { get; set; } = null!;
|
|
|
|
[Required]
|
|
[Column("expiration")]
|
|
public DateTimeOffset Expiration { get; set; }
|
|
|
|
public enum OnPayBehavior
|
|
{
|
|
/// <summary>
|
|
/// Starts the plan if payment is due, else, do not and add the funds to the credit.
|
|
/// </summary>
|
|
SoftMigration,
|
|
/// <summary>
|
|
/// Starts the plan immediately. If a payment wasn't due yet, reimburse the unused part of the period,
|
|
/// and start the plan.
|
|
/// </summary>
|
|
HardMigration
|
|
}
|
|
|
|
public string? GetRedirectUrl()
|
|
{
|
|
if (SuccessRedirectUrl is null)
|
|
return null;
|
|
// Add ?checkoutPlanId=... to the redirect URL
|
|
try { return QueryHelpers.AddQueryString(SuccessRedirectUrl, "checkoutPlanId", Id); }
|
|
catch (UriFormatException) { return null; }
|
|
}
|
|
|
|
public static void OnModelCreating(ModelBuilder builder, DatabaseFacade databaseFacade)
|
|
{
|
|
var b = builder.Entity<PlanCheckoutData>();
|
|
OnModelCreateBase(b, builder, databaseFacade);
|
|
b.Property(x => x.Id)
|
|
.ValueGeneratedOnAdd()
|
|
.HasValueGenerator(ValueGenerators.WithPrefix("plancheckout"));
|
|
|
|
b.Property(x => x.InvoiceMetadata).HasColumnName("invoice_metadata").HasColumnType("jsonb")
|
|
.HasDefaultValueSql("'{}'::jsonb");
|
|
b.Property(x => x.NewSubscriberMetadata).HasColumnName("new_subscriber_metadata").HasColumnType("jsonb")
|
|
.HasDefaultValueSql("'{}'::jsonb");
|
|
|
|
b.Property(x => x.BaseUrl)
|
|
.HasConversion<string>(
|
|
x => x.ToString(),
|
|
x => RequestBaseUrl.FromUrl(x)
|
|
);
|
|
|
|
b.HasIndex(x => x.Expiration);
|
|
b.Property(x => x.Expiration).HasDefaultValueSql("now() + interval '1 day'");
|
|
b.Property(x => x.OnPay).HasDefaultValue(OnPayBehavior.SoftMigration).HasConversion<string>();
|
|
b.Property(x => x.IsTrial).HasDefaultValue(false);
|
|
b.HasOne(x => x.Plan).WithMany().OnDelete(DeleteBehavior.Cascade);
|
|
b.HasOne(x => x.Subscriber).WithMany().OnDelete(DeleteBehavior.SetNull);
|
|
b.HasOne(x => x.Invoice).WithMany().OnDelete(DeleteBehavior.SetNull);
|
|
}
|
|
|
|
[NotMapped]
|
|
public bool IsExpired => DateTimeOffset.UtcNow > Expiration;
|
|
}
|