380 lines
15 KiB
Transact-SQL
380 lines
15 KiB
Transact-SQL
SET ANSI_NULLS ON;
|
|
GO
|
|
SET QUOTED_IDENTIFIER ON;
|
|
GO
|
|
|
|
IF NOT EXISTS (SELECT 1 FROM sys.columns WHERE object_id = OBJECT_ID(N'dbo.SubscriptionLevel') AND name = N'StripeMonthlyPriceId')
|
|
ALTER TABLE dbo.SubscriptionLevel ADD StripeMonthlyPriceId nvarchar(100) NULL;
|
|
GO
|
|
|
|
IF NOT EXISTS (SELECT 1 FROM sys.columns WHERE object_id = OBJECT_ID(N'dbo.SubscriptionLevel') AND name = N'StripeAnnualPriceId')
|
|
ALTER TABLE dbo.SubscriptionLevel ADD StripeAnnualPriceId nvarchar(100) NULL;
|
|
GO
|
|
|
|
IF NOT EXISTS (SELECT 1 FROM sys.columns WHERE object_id = OBJECT_ID(N'dbo.SubscriptionLevel') AND name = N'RequiresStripeSubscription')
|
|
ALTER TABLE dbo.SubscriptionLevel ADD RequiresStripeSubscription bit NOT NULL CONSTRAINT DF_SubscriptionLevel_RequiresStripeSubscription DEFAULT 0;
|
|
GO
|
|
|
|
IF NOT EXISTS (SELECT 1 FROM sys.columns WHERE object_id = OBJECT_ID(N'dbo.UserSubscription') AND name = N'StripeCustomerId')
|
|
ALTER TABLE dbo.UserSubscription ADD StripeCustomerId nvarchar(100) NULL;
|
|
GO
|
|
|
|
IF NOT EXISTS (SELECT 1 FROM sys.columns WHERE object_id = OBJECT_ID(N'dbo.UserSubscription') AND name = N'StripeSubscriptionId')
|
|
ALTER TABLE dbo.UserSubscription ADD StripeSubscriptionId nvarchar(100) NULL;
|
|
GO
|
|
|
|
IF NOT EXISTS (SELECT 1 FROM sys.columns WHERE object_id = OBJECT_ID(N'dbo.UserSubscription') AND name = N'StripePriceId')
|
|
ALTER TABLE dbo.UserSubscription ADD StripePriceId nvarchar(100) NULL;
|
|
GO
|
|
|
|
IF NOT EXISTS (SELECT 1 FROM sys.columns WHERE object_id = OBJECT_ID(N'dbo.UserSubscription') AND name = N'BillingInterval')
|
|
ALTER TABLE dbo.UserSubscription ADD BillingInterval nvarchar(20) NULL;
|
|
GO
|
|
|
|
IF NOT EXISTS (SELECT 1 FROM sys.columns WHERE object_id = OBJECT_ID(N'dbo.UserSubscription') AND name = N'StripeStatus')
|
|
ALTER TABLE dbo.UserSubscription ADD StripeStatus nvarchar(50) NULL;
|
|
GO
|
|
|
|
IF NOT EXISTS (SELECT 1 FROM sys.columns WHERE object_id = OBJECT_ID(N'dbo.UserSubscription') AND name = N'CurrentPeriodStartUTC')
|
|
ALTER TABLE dbo.UserSubscription ADD CurrentPeriodStartUTC datetime2 NULL;
|
|
GO
|
|
|
|
IF NOT EXISTS (SELECT 1 FROM sys.columns WHERE object_id = OBJECT_ID(N'dbo.UserSubscription') AND name = N'CurrentPeriodEndUTC')
|
|
ALTER TABLE dbo.UserSubscription ADD CurrentPeriodEndUTC datetime2 NULL;
|
|
GO
|
|
|
|
IF NOT EXISTS (SELECT 1 FROM sys.columns WHERE object_id = OBJECT_ID(N'dbo.UserSubscription') AND name = N'CancelAtPeriodEnd')
|
|
ALTER TABLE dbo.UserSubscription ADD CancelAtPeriodEnd bit NOT NULL CONSTRAINT DF_UserSubscription_CancelAtPeriodEnd DEFAULT 0;
|
|
GO
|
|
|
|
IF NOT EXISTS (SELECT 1 FROM sys.columns WHERE object_id = OBJECT_ID(N'dbo.UserSubscription') AND name = N'CancelledDateUTC')
|
|
ALTER TABLE dbo.UserSubscription ADD CancelledDateUTC datetime2 NULL;
|
|
GO
|
|
|
|
IF NOT EXISTS (SELECT 1 FROM sys.columns WHERE object_id = OBJECT_ID(N'dbo.UserSubscription') AND name = N'LastPaymentFailureDateUTC')
|
|
ALTER TABLE dbo.UserSubscription ADD LastPaymentFailureDateUTC datetime2 NULL;
|
|
GO
|
|
|
|
IF NOT EXISTS (SELECT 1 FROM sys.columns WHERE object_id = OBJECT_ID(N'dbo.UserSubscription') AND name = N'LastStripeEventId')
|
|
ALTER TABLE dbo.UserSubscription ADD LastStripeEventId nvarchar(100) NULL;
|
|
GO
|
|
|
|
IF OBJECT_ID(N'dbo.StripeWebhookEvent', N'U') IS NULL
|
|
BEGIN
|
|
CREATE TABLE dbo.StripeWebhookEvent
|
|
(
|
|
StripeWebhookEventID bigint IDENTITY(1,1) NOT NULL CONSTRAINT PK_StripeWebhookEvent PRIMARY KEY,
|
|
StripeEventId nvarchar(100) NOT NULL,
|
|
EventType nvarchar(100) NOT NULL,
|
|
ReceivedDateUTC datetime2 NOT NULL CONSTRAINT DF_StripeWebhookEvent_ReceivedDateUTC DEFAULT SYSUTCDATETIME(),
|
|
ProcessedDateUTC datetime2 NULL,
|
|
ProcessingStatus nvarchar(50) NOT NULL CONSTRAINT DF_StripeWebhookEvent_ProcessingStatus DEFAULT N'Received',
|
|
ErrorMessage nvarchar(1000) NULL,
|
|
CONSTRAINT UX_StripeWebhookEvent_EventId UNIQUE (StripeEventId)
|
|
);
|
|
END;
|
|
GO
|
|
|
|
IF NOT EXISTS (SELECT 1 FROM sys.indexes WHERE name = N'IX_UserSubscription_StripeSubscriptionId' AND object_id = OBJECT_ID(N'dbo.UserSubscription'))
|
|
CREATE INDEX IX_UserSubscription_StripeSubscriptionId ON dbo.UserSubscription(StripeSubscriptionId) WHERE StripeSubscriptionId IS NOT NULL;
|
|
GO
|
|
|
|
IF NOT EXISTS (SELECT 1 FROM sys.indexes WHERE name = N'IX_UserSubscription_StripeCustomerId' AND object_id = OBJECT_ID(N'dbo.UserSubscription'))
|
|
CREATE INDEX IX_UserSubscription_StripeCustomerId ON dbo.UserSubscription(StripeCustomerId) WHERE StripeCustomerId IS NOT NULL;
|
|
GO
|
|
|
|
UPDATE dbo.SubscriptionLevel
|
|
SET RequiresStripeSubscription = CASE WHEN Name = N'DraftDesk' THEN 0 ELSE 1 END,
|
|
StripeMonthlyPriceId = CASE Name
|
|
WHEN N'WritingRoom' THEN N'price_1TffeZIH8aCkpHgj4AlC7Atv'
|
|
WHEN N'StoryForge' THEN N'price_1TffdJIH8aCkpHgjvQfV7heX'
|
|
WHEN N'AuthorStudio' THEN N'price_1TffbaIH8aCkpHgjKFLoaHMJ'
|
|
ELSE NULL
|
|
END,
|
|
StripeAnnualPriceId = CASE Name
|
|
WHEN N'WritingRoom' THEN N'price_1Tffe8IH8aCkpHgj25QRMu4t'
|
|
WHEN N'StoryForge' THEN N'price_1TffccIH8aCkpHgjXlSwB4A1'
|
|
WHEN N'AuthorStudio' THEN N'price_1TffaRIH8aCkpHgjIoQqgwBH'
|
|
ELSE NULL
|
|
END,
|
|
ModifiedDateUTC = SYSUTCDATETIME();
|
|
GO
|
|
|
|
CREATE OR ALTER PROCEDURE dbo.SubscriptionLevel_ListActive
|
|
AS
|
|
BEGIN
|
|
SET NOCOUNT ON;
|
|
|
|
SELECT SubscriptionLevelID, Name, DisplayName, Description, MaxBooks, MaxChaptersPerBook,
|
|
MaxScenesPerBook, MaxCharactersPerProject, MaxStorageMB, MaxCollaborators, IsActive,
|
|
SortOrder, CreatedDateUTC, ModifiedDateUTC, StripeMonthlyPriceId, StripeAnnualPriceId,
|
|
RequiresStripeSubscription
|
|
FROM dbo.SubscriptionLevel
|
|
WHERE IsActive = 1
|
|
ORDER BY SortOrder, DisplayName;
|
|
END;
|
|
GO
|
|
|
|
CREATE OR ALTER PROCEDURE dbo.SubscriptionLevel_Get
|
|
@SubscriptionLevelID int
|
|
AS
|
|
BEGIN
|
|
SET NOCOUNT ON;
|
|
|
|
SELECT SubscriptionLevelID, Name, DisplayName, Description, MaxBooks, MaxChaptersPerBook,
|
|
MaxScenesPerBook, MaxCharactersPerProject, MaxStorageMB, MaxCollaborators, IsActive,
|
|
SortOrder, CreatedDateUTC, ModifiedDateUTC, StripeMonthlyPriceId, StripeAnnualPriceId,
|
|
RequiresStripeSubscription
|
|
FROM dbo.SubscriptionLevel
|
|
WHERE SubscriptionLevelID = @SubscriptionLevelID;
|
|
END;
|
|
GO
|
|
|
|
CREATE OR ALTER PROCEDURE dbo.SubscriptionLevel_GetByStripePrice
|
|
@StripePriceId nvarchar(100)
|
|
AS
|
|
BEGIN
|
|
SET NOCOUNT ON;
|
|
|
|
SELECT SubscriptionLevelID, Name, DisplayName, Description, MaxBooks, MaxChaptersPerBook,
|
|
MaxScenesPerBook, MaxCharactersPerProject, MaxStorageMB, MaxCollaborators, IsActive,
|
|
SortOrder, CreatedDateUTC, ModifiedDateUTC, StripeMonthlyPriceId, StripeAnnualPriceId,
|
|
RequiresStripeSubscription,
|
|
CASE
|
|
WHEN StripeMonthlyPriceId = @StripePriceId THEN N'Monthly'
|
|
WHEN StripeAnnualPriceId = @StripePriceId THEN N'Annual'
|
|
ELSE NULL
|
|
END AS BillingInterval
|
|
FROM dbo.SubscriptionLevel
|
|
WHERE IsActive = 1
|
|
AND RequiresStripeSubscription = 1
|
|
AND (StripeMonthlyPriceId = @StripePriceId OR StripeAnnualPriceId = @StripePriceId);
|
|
END;
|
|
GO
|
|
|
|
CREATE OR ALTER PROCEDURE dbo.UserSubscription_GetCurrent
|
|
@UserID int
|
|
AS
|
|
BEGIN
|
|
SET NOCOUNT ON;
|
|
|
|
SELECT us.UserSubscriptionID, us.UserID, us.SubscriptionLevelID, us.StartDateUTC, us.EndDateUTC,
|
|
us.IsActive, us.IsTrial, us.TrialExpiryDateUTC, us.CreatedDateUTC, us.ModifiedDateUTC,
|
|
us.StripeCustomerId, us.StripeSubscriptionId, us.StripePriceId, us.BillingInterval, us.StripeStatus,
|
|
us.CurrentPeriodStartUTC, us.CurrentPeriodEndUTC, us.CancelAtPeriodEnd, us.CancelledDateUTC,
|
|
us.LastPaymentFailureDateUTC, us.LastStripeEventId,
|
|
sl.Name, sl.DisplayName, sl.Description, sl.MaxBooks, sl.MaxChaptersPerBook,
|
|
sl.MaxScenesPerBook, sl.MaxCharactersPerProject, sl.MaxStorageMB, sl.MaxCollaborators,
|
|
sl.IsActive AS SubscriptionLevelIsActive, sl.SortOrder, sl.StripeMonthlyPriceId,
|
|
sl.StripeAnnualPriceId, sl.RequiresStripeSubscription
|
|
FROM dbo.UserSubscription us
|
|
INNER JOIN dbo.SubscriptionLevel sl ON sl.SubscriptionLevelID = us.SubscriptionLevelID
|
|
WHERE us.UserID = @UserID
|
|
AND us.IsActive = 1
|
|
AND (us.EndDateUTC IS NULL OR us.EndDateUTC > SYSUTCDATETIME());
|
|
END;
|
|
GO
|
|
|
|
CREATE OR ALTER PROCEDURE dbo.UserSubscription_SetStripeCustomer
|
|
@UserID int,
|
|
@StripeCustomerId nvarchar(100)
|
|
AS
|
|
BEGIN
|
|
SET NOCOUNT ON;
|
|
|
|
UPDATE dbo.UserSubscription
|
|
SET StripeCustomerId = @StripeCustomerId,
|
|
ModifiedDateUTC = SYSUTCDATETIME()
|
|
WHERE UserID = @UserID
|
|
AND IsActive = 1;
|
|
END;
|
|
GO
|
|
|
|
CREATE OR ALTER PROCEDURE dbo.StripeWebhookEvent_TryBegin
|
|
@StripeEventId nvarchar(100),
|
|
@EventType nvarchar(100)
|
|
AS
|
|
BEGIN
|
|
SET NOCOUNT ON;
|
|
|
|
IF EXISTS (SELECT 1 FROM dbo.StripeWebhookEvent WHERE StripeEventId = @StripeEventId)
|
|
BEGIN
|
|
SELECT CAST(0 AS bit) AS ShouldProcess;
|
|
RETURN;
|
|
END;
|
|
|
|
INSERT dbo.StripeWebhookEvent (StripeEventId, EventType)
|
|
VALUES (@StripeEventId, @EventType);
|
|
|
|
SELECT CAST(1 AS bit) AS ShouldProcess;
|
|
END;
|
|
GO
|
|
|
|
CREATE OR ALTER PROCEDURE dbo.StripeWebhookEvent_Complete
|
|
@StripeEventId nvarchar(100),
|
|
@ProcessingStatus nvarchar(50),
|
|
@ErrorMessage nvarchar(1000) = NULL
|
|
AS
|
|
BEGIN
|
|
SET NOCOUNT ON;
|
|
|
|
UPDATE dbo.StripeWebhookEvent
|
|
SET ProcessingStatus = @ProcessingStatus,
|
|
ProcessedDateUTC = SYSUTCDATETIME(),
|
|
ErrorMessage = @ErrorMessage
|
|
WHERE StripeEventId = @StripeEventId;
|
|
END;
|
|
GO
|
|
|
|
CREATE OR ALTER PROCEDURE dbo.UserSubscription_ApplyStripeState
|
|
@UserID int = NULL,
|
|
@SubscriptionLevelID int = NULL,
|
|
@StripeCustomerId nvarchar(100),
|
|
@StripeSubscriptionId nvarchar(100),
|
|
@StripePriceId nvarchar(100),
|
|
@BillingInterval nvarchar(20),
|
|
@StripeStatus nvarchar(50),
|
|
@CurrentPeriodStartUTC datetime2 = NULL,
|
|
@CurrentPeriodEndUTC datetime2 = NULL,
|
|
@CancelAtPeriodEnd bit = 0,
|
|
@LastStripeEventId nvarchar(100) = NULL
|
|
AS
|
|
BEGIN
|
|
SET NOCOUNT ON;
|
|
|
|
IF @SubscriptionLevelID IS NULL
|
|
SELECT @SubscriptionLevelID = SubscriptionLevelID
|
|
FROM dbo.SubscriptionLevel
|
|
WHERE IsActive = 1
|
|
AND (StripeMonthlyPriceId = @StripePriceId OR StripeAnnualPriceId = @StripePriceId);
|
|
|
|
IF @BillingInterval IS NULL
|
|
SELECT @BillingInterval = CASE
|
|
WHEN StripeMonthlyPriceId = @StripePriceId THEN N'Monthly'
|
|
WHEN StripeAnnualPriceId = @StripePriceId THEN N'Annual'
|
|
ELSE NULL
|
|
END
|
|
FROM dbo.SubscriptionLevel
|
|
WHERE SubscriptionLevelID = @SubscriptionLevelID;
|
|
|
|
IF @UserID IS NULL
|
|
SELECT TOP (1) @UserID = UserID
|
|
FROM dbo.UserSubscription
|
|
WHERE StripeSubscriptionId = @StripeSubscriptionId
|
|
OR StripeCustomerId = @StripeCustomerId
|
|
ORDER BY IsActive DESC, ModifiedDateUTC DESC;
|
|
|
|
IF @UserID IS NULL OR @SubscriptionLevelID IS NULL
|
|
RETURN;
|
|
|
|
DECLARE @ExistingSubscriptionID int;
|
|
SELECT TOP (1) @ExistingSubscriptionID = UserSubscriptionID
|
|
FROM dbo.UserSubscription
|
|
WHERE UserID = @UserID
|
|
AND IsActive = 1
|
|
ORDER BY UserSubscriptionID DESC;
|
|
|
|
IF @ExistingSubscriptionID IS NULL
|
|
BEGIN
|
|
INSERT dbo.UserSubscription
|
|
(
|
|
UserID, SubscriptionLevelID, StartDateUTC, EndDateUTC, IsActive, IsTrial, TrialExpiryDateUTC,
|
|
StripeCustomerId, StripeSubscriptionId, StripePriceId, BillingInterval, StripeStatus,
|
|
CurrentPeriodStartUTC, CurrentPeriodEndUTC, CancelAtPeriodEnd, LastStripeEventId
|
|
)
|
|
VALUES
|
|
(
|
|
@UserID, @SubscriptionLevelID, COALESCE(@CurrentPeriodStartUTC, SYSUTCDATETIME()), NULL, 1, 0, NULL,
|
|
@StripeCustomerId, @StripeSubscriptionId, @StripePriceId, @BillingInterval, @StripeStatus,
|
|
@CurrentPeriodStartUTC, @CurrentPeriodEndUTC, @CancelAtPeriodEnd, @LastStripeEventId
|
|
);
|
|
END
|
|
ELSE
|
|
BEGIN
|
|
UPDATE dbo.UserSubscription
|
|
SET SubscriptionLevelID = @SubscriptionLevelID,
|
|
EndDateUTC = NULL,
|
|
IsActive = 1,
|
|
IsTrial = 0,
|
|
TrialExpiryDateUTC = NULL,
|
|
StripeCustomerId = @StripeCustomerId,
|
|
StripeSubscriptionId = @StripeSubscriptionId,
|
|
StripePriceId = @StripePriceId,
|
|
BillingInterval = @BillingInterval,
|
|
StripeStatus = @StripeStatus,
|
|
CurrentPeriodStartUTC = @CurrentPeriodStartUTC,
|
|
CurrentPeriodEndUTC = @CurrentPeriodEndUTC,
|
|
CancelAtPeriodEnd = @CancelAtPeriodEnd,
|
|
CancelledDateUTC = CASE WHEN @StripeStatus = N'canceled' THEN COALESCE(CancelledDateUTC, SYSUTCDATETIME()) ELSE NULL END,
|
|
LastPaymentFailureDateUTC = CASE WHEN @StripeStatus IN (N'active', N'trialing') THEN NULL ELSE LastPaymentFailureDateUTC END,
|
|
LastStripeEventId = @LastStripeEventId,
|
|
ModifiedDateUTC = SYSUTCDATETIME()
|
|
WHERE UserSubscriptionID = @ExistingSubscriptionID;
|
|
END;
|
|
END;
|
|
GO
|
|
|
|
CREATE OR ALTER PROCEDURE dbo.UserSubscription_DowngradeToDraftDesk
|
|
@StripeCustomerId nvarchar(100) = NULL,
|
|
@StripeSubscriptionId nvarchar(100) = NULL,
|
|
@LastStripeEventId nvarchar(100) = NULL
|
|
AS
|
|
BEGIN
|
|
SET NOCOUNT ON;
|
|
|
|
DECLARE @DraftDeskID int;
|
|
SELECT @DraftDeskID = SubscriptionLevelID FROM dbo.SubscriptionLevel WHERE Name = N'DraftDesk';
|
|
|
|
IF @DraftDeskID IS NULL
|
|
RETURN;
|
|
|
|
UPDATE dbo.UserSubscription
|
|
SET SubscriptionLevelID = @DraftDeskID,
|
|
EndDateUTC = NULL,
|
|
IsActive = 1,
|
|
IsTrial = 0,
|
|
TrialExpiryDateUTC = NULL,
|
|
StripeStatus = N'canceled',
|
|
CancelAtPeriodEnd = 0,
|
|
CancelledDateUTC = COALESCE(CancelledDateUTC, SYSUTCDATETIME()),
|
|
LastStripeEventId = @LastStripeEventId,
|
|
ModifiedDateUTC = SYSUTCDATETIME()
|
|
WHERE (@StripeSubscriptionId IS NOT NULL AND StripeSubscriptionId = @StripeSubscriptionId)
|
|
OR (@StripeCustomerId IS NOT NULL AND StripeCustomerId = @StripeCustomerId);
|
|
END;
|
|
GO
|
|
|
|
CREATE OR ALTER PROCEDURE dbo.UserSubscription_RecordPaymentFailure
|
|
@StripeCustomerId nvarchar(100) = NULL,
|
|
@StripeSubscriptionId nvarchar(100) = NULL,
|
|
@LastStripeEventId nvarchar(100) = NULL
|
|
AS
|
|
BEGIN
|
|
SET NOCOUNT ON;
|
|
|
|
UPDATE dbo.UserSubscription
|
|
SET LastPaymentFailureDateUTC = SYSUTCDATETIME(),
|
|
LastStripeEventId = @LastStripeEventId,
|
|
ModifiedDateUTC = SYSUTCDATETIME()
|
|
WHERE (@StripeSubscriptionId IS NOT NULL AND StripeSubscriptionId = @StripeSubscriptionId)
|
|
OR (@StripeCustomerId IS NOT NULL AND StripeCustomerId = @StripeCustomerId);
|
|
END;
|
|
GO
|
|
|
|
CREATE OR ALTER PROCEDURE dbo.UserSubscription_ClearPaymentFailure
|
|
@StripeCustomerId nvarchar(100) = NULL,
|
|
@StripeSubscriptionId nvarchar(100) = NULL,
|
|
@LastStripeEventId nvarchar(100) = NULL
|
|
AS
|
|
BEGIN
|
|
SET NOCOUNT ON;
|
|
|
|
UPDATE dbo.UserSubscription
|
|
SET LastPaymentFailureDateUTC = NULL,
|
|
LastStripeEventId = @LastStripeEventId,
|
|
ModifiedDateUTC = SYSUTCDATETIME()
|
|
WHERE (@StripeSubscriptionId IS NOT NULL AND StripeSubscriptionId = @StripeSubscriptionId)
|
|
OR (@StripeCustomerId IS NOT NULL AND StripeCustomerId = @StripeCustomerId);
|
|
END;
|
|
GO
|