183 lines
8.3 KiB
C#
183 lines
8.3 KiB
C#
using System.Data;
|
|
using Dapper;
|
|
using PlotLine.Models;
|
|
|
|
namespace PlotLine.Data;
|
|
|
|
public interface ISubscriptionRepository
|
|
{
|
|
Task<UserSubscriptionDetail?> GetCurrentSubscriptionAsync(int userId);
|
|
Task<SubscriptionLevel?> GetSubscriptionLevelAsync(int subscriptionLevelId);
|
|
Task<IReadOnlyList<SubscriptionLevel>> GetActiveSubscriptionLevelsAsync();
|
|
Task<int> GetOwnedBookCountAsync(int userId);
|
|
Task<int> GetChapterCountForBookAsync(int bookId);
|
|
Task<int> GetSceneCountForBookAsync(int bookId);
|
|
Task<int> GetCharacterCountForProjectAsync(int projectId);
|
|
Task<int> GetCollaboratorCountForOwnerAsync(int userId);
|
|
Task<SubscriptionUsageSummary> GetUsageSummaryForOwnerAsync(int userId);
|
|
Task<SubscriptionLevel?> GetSubscriptionLevelByStripePriceAsync(string stripePriceId);
|
|
Task SetStripeCustomerAsync(int userId, string stripeCustomerId);
|
|
Task<bool> TryBeginStripeWebhookEventAsync(string stripeEventId, string eventType);
|
|
Task CompleteStripeWebhookEventAsync(string stripeEventId, string processingStatus, string? errorMessage = null);
|
|
Task ApplyStripeStateAsync(StripeSubscriptionSyncState state);
|
|
Task DowngradeToDraftDeskAsync(string? stripeCustomerId, string? stripeSubscriptionId, string? lastStripeEventId);
|
|
Task RecordPaymentFailureAsync(string? stripeCustomerId, string? stripeSubscriptionId, string? lastStripeEventId);
|
|
Task ClearPaymentFailureAsync(string? stripeCustomerId, string? stripeSubscriptionId, string? lastStripeEventId);
|
|
}
|
|
|
|
public sealed class SubscriptionRepository(ISqlConnectionFactory connectionFactory) : ISubscriptionRepository
|
|
{
|
|
public async Task<UserSubscriptionDetail?> GetCurrentSubscriptionAsync(int userId)
|
|
{
|
|
using var connection = connectionFactory.CreateConnection();
|
|
return await connection.QuerySingleOrDefaultAsync<UserSubscriptionDetail>(
|
|
"dbo.UserSubscription_GetCurrent",
|
|
new { UserID = userId },
|
|
commandType: CommandType.StoredProcedure);
|
|
}
|
|
|
|
public async Task<SubscriptionLevel?> GetSubscriptionLevelAsync(int subscriptionLevelId)
|
|
{
|
|
using var connection = connectionFactory.CreateConnection();
|
|
return await connection.QuerySingleOrDefaultAsync<SubscriptionLevel>(
|
|
"dbo.SubscriptionLevel_Get",
|
|
new { SubscriptionLevelID = subscriptionLevelId },
|
|
commandType: CommandType.StoredProcedure);
|
|
}
|
|
|
|
public async Task<IReadOnlyList<SubscriptionLevel>> GetActiveSubscriptionLevelsAsync()
|
|
{
|
|
using var connection = connectionFactory.CreateConnection();
|
|
var rows = await connection.QueryAsync<SubscriptionLevel>(
|
|
"dbo.SubscriptionLevel_ListActive",
|
|
commandType: CommandType.StoredProcedure);
|
|
return rows.ToList();
|
|
}
|
|
|
|
public async Task<int> GetOwnedBookCountAsync(int userId)
|
|
{
|
|
using var connection = connectionFactory.CreateConnection();
|
|
return await connection.QuerySingleAsync<int>(
|
|
"dbo.SubscriptionUsage_BookCountForOwner",
|
|
new { UserID = userId },
|
|
commandType: CommandType.StoredProcedure);
|
|
}
|
|
|
|
public async Task<int> GetChapterCountForBookAsync(int bookId)
|
|
{
|
|
using var connection = connectionFactory.CreateConnection();
|
|
return await connection.QuerySingleAsync<int>(
|
|
"dbo.SubscriptionUsage_ChapterCountForBook",
|
|
new { BookID = bookId },
|
|
commandType: CommandType.StoredProcedure);
|
|
}
|
|
|
|
public async Task<int> GetSceneCountForBookAsync(int bookId)
|
|
{
|
|
using var connection = connectionFactory.CreateConnection();
|
|
return await connection.QuerySingleAsync<int>(
|
|
"dbo.SubscriptionUsage_SceneCountForBook",
|
|
new { BookID = bookId },
|
|
commandType: CommandType.StoredProcedure);
|
|
}
|
|
|
|
public async Task<int> GetCharacterCountForProjectAsync(int projectId)
|
|
{
|
|
using var connection = connectionFactory.CreateConnection();
|
|
return await connection.QuerySingleAsync<int>(
|
|
"dbo.SubscriptionUsage_CharacterCountForProject",
|
|
new { ProjectID = projectId },
|
|
commandType: CommandType.StoredProcedure);
|
|
}
|
|
|
|
public async Task<int> GetCollaboratorCountForOwnerAsync(int userId)
|
|
{
|
|
using var connection = connectionFactory.CreateConnection();
|
|
return await connection.QuerySingleAsync<int>(
|
|
"dbo.SubscriptionUsage_CollaboratorCountForOwner",
|
|
new { UserID = userId },
|
|
commandType: CommandType.StoredProcedure);
|
|
}
|
|
|
|
public async Task<SubscriptionUsageSummary> GetUsageSummaryForOwnerAsync(int userId)
|
|
{
|
|
using var connection = connectionFactory.CreateConnection();
|
|
return await connection.QuerySingleAsync<SubscriptionUsageSummary>(
|
|
"dbo.SubscriptionUsage_GetSummaryForOwner",
|
|
new { UserID = userId },
|
|
commandType: CommandType.StoredProcedure);
|
|
}
|
|
|
|
public async Task<SubscriptionLevel?> GetSubscriptionLevelByStripePriceAsync(string stripePriceId)
|
|
{
|
|
using var connection = connectionFactory.CreateConnection();
|
|
return await connection.QuerySingleOrDefaultAsync<SubscriptionLevel>(
|
|
"dbo.SubscriptionLevel_GetByStripePrice",
|
|
new { StripePriceId = stripePriceId },
|
|
commandType: CommandType.StoredProcedure);
|
|
}
|
|
|
|
public async Task SetStripeCustomerAsync(int userId, string stripeCustomerId)
|
|
{
|
|
using var connection = connectionFactory.CreateConnection();
|
|
await connection.ExecuteAsync(
|
|
"dbo.UserSubscription_SetStripeCustomer",
|
|
new { UserID = userId, StripeCustomerId = stripeCustomerId },
|
|
commandType: CommandType.StoredProcedure);
|
|
}
|
|
|
|
public async Task<bool> TryBeginStripeWebhookEventAsync(string stripeEventId, string eventType)
|
|
{
|
|
using var connection = connectionFactory.CreateConnection();
|
|
return await connection.QuerySingleAsync<bool>(
|
|
"dbo.StripeWebhookEvent_TryBegin",
|
|
new { StripeEventId = stripeEventId, EventType = eventType },
|
|
commandType: CommandType.StoredProcedure);
|
|
}
|
|
|
|
public async Task CompleteStripeWebhookEventAsync(string stripeEventId, string processingStatus, string? errorMessage = null)
|
|
{
|
|
using var connection = connectionFactory.CreateConnection();
|
|
await connection.ExecuteAsync(
|
|
"dbo.StripeWebhookEvent_Complete",
|
|
new { StripeEventId = stripeEventId, ProcessingStatus = processingStatus, ErrorMessage = errorMessage },
|
|
commandType: CommandType.StoredProcedure);
|
|
}
|
|
|
|
public async Task ApplyStripeStateAsync(StripeSubscriptionSyncState state)
|
|
{
|
|
using var connection = connectionFactory.CreateConnection();
|
|
await connection.ExecuteAsync(
|
|
"dbo.UserSubscription_ApplyStripeState",
|
|
state,
|
|
commandType: CommandType.StoredProcedure);
|
|
}
|
|
|
|
public async Task DowngradeToDraftDeskAsync(string? stripeCustomerId, string? stripeSubscriptionId, string? lastStripeEventId)
|
|
{
|
|
using var connection = connectionFactory.CreateConnection();
|
|
await connection.ExecuteAsync(
|
|
"dbo.UserSubscription_DowngradeToDraftDesk",
|
|
new { StripeCustomerId = stripeCustomerId, StripeSubscriptionId = stripeSubscriptionId, LastStripeEventId = lastStripeEventId },
|
|
commandType: CommandType.StoredProcedure);
|
|
}
|
|
|
|
public async Task RecordPaymentFailureAsync(string? stripeCustomerId, string? stripeSubscriptionId, string? lastStripeEventId)
|
|
{
|
|
using var connection = connectionFactory.CreateConnection();
|
|
await connection.ExecuteAsync(
|
|
"dbo.UserSubscription_RecordPaymentFailure",
|
|
new { StripeCustomerId = stripeCustomerId, StripeSubscriptionId = stripeSubscriptionId, LastStripeEventId = lastStripeEventId },
|
|
commandType: CommandType.StoredProcedure);
|
|
}
|
|
|
|
public async Task ClearPaymentFailureAsync(string? stripeCustomerId, string? stripeSubscriptionId, string? lastStripeEventId)
|
|
{
|
|
using var connection = connectionFactory.CreateConnection();
|
|
await connection.ExecuteAsync(
|
|
"dbo.UserSubscription_ClearPaymentFailure",
|
|
new { StripeCustomerId = stripeCustomerId, StripeSubscriptionId = stripeSubscriptionId, LastStripeEventId = lastStripeEventId },
|
|
commandType: CommandType.StoredProcedure);
|
|
}
|
|
}
|