SET ANSI_NULLS ON; GO SET QUOTED_IDENTIFIER ON; GO IF COL_LENGTH('dbo.SceneDependencies', 'ProjectID') IS NULL BEGIN ALTER TABLE dbo.SceneDependencies ADD ProjectID int NULL; END; GO UPDATE sd SET ProjectID = b.ProjectID FROM dbo.SceneDependencies sd INNER JOIN dbo.Scenes s ON s.SceneID = sd.SourceSceneID INNER JOIN dbo.Chapters c ON c.ChapterID = s.ChapterID INNER JOIN dbo.Books b ON b.BookID = c.BookID WHERE sd.ProjectID IS NULL; GO IF COL_LENGTH('dbo.SceneDependencies', 'IsHardDependency') IS NULL BEGIN ALTER TABLE dbo.SceneDependencies ADD IsHardDependency bit NOT NULL CONSTRAINT DF_SceneDependencies_IsHardDependency DEFAULT 0; END; GO MERGE dbo.SceneDependencyTypes AS target USING (VALUES (N'Must Occur Before', 10), (N'Emotional Setup', 20), (N'Reveal Setup', 30), (N'Action Consequence', 40), (N'Travel Dependency', 50), (N'Relationship Dependency', 60), (N'Knowledge Dependency', 70), (N'Object Dependency', 80), (N'Location Dependency', 90), (N'Time Dependency', 100) ) AS source (TypeName, SortOrder) ON target.TypeName = source.TypeName WHEN NOT MATCHED THEN INSERT (TypeName, SortOrder) VALUES (source.TypeName, source.SortOrder); GO CREATE OR ALTER PROCEDURE dbo.SceneDependencyLookup_All AS BEGIN SET NOCOUNT ON; SELECT SceneDependencyTypeID, TypeName, SortOrder, IsActive FROM dbo.SceneDependencyTypes WHERE IsActive = 1 ORDER BY SortOrder; END; GO CREATE OR ALTER PROCEDURE dbo.SceneDependency_Save @SceneDependencyID int = NULL, @ProjectID int = NULL, @SourceSceneID int, @TargetSceneID int, @SceneDependencyTypeID int, @Description nvarchar(max) = NULL, @IsHardDependency bit = 0 AS BEGIN SET NOCOUNT ON; IF @ProjectID IS NULL BEGIN SELECT @ProjectID = b.ProjectID FROM dbo.Scenes s INNER JOIN dbo.Chapters c ON c.ChapterID = s.ChapterID INNER JOIN dbo.Books b ON b.BookID = c.BookID WHERE s.SceneID = @SourceSceneID; END; IF @SourceSceneID = @TargetSceneID RETURN; IF @SceneDependencyID IS NULL OR @SceneDependencyID = 0 BEGIN INSERT dbo.SceneDependencies (ProjectID, SourceSceneID, TargetSceneID, SceneDependencyTypeID, Description, IsHardDependency) VALUES (@ProjectID, @SourceSceneID, @TargetSceneID, @SceneDependencyTypeID, @Description, @IsHardDependency); SELECT CAST(SCOPE_IDENTITY() AS int); RETURN; END; UPDATE dbo.SceneDependencies SET SourceSceneID = @SourceSceneID, TargetSceneID = @TargetSceneID, SceneDependencyTypeID = @SceneDependencyTypeID, Description = @Description, IsHardDependency = @IsHardDependency, UpdatedDate = SYSUTCDATETIME() WHERE SceneDependencyID = @SceneDependencyID; SELECT @SceneDependencyID; END; GO CREATE OR ALTER PROCEDURE dbo.SceneDependency_Archive @SceneDependencyID int AS BEGIN SET NOCOUNT ON; UPDATE dbo.SceneDependencies SET IsArchived = 1, UpdatedDate = SYSUTCDATETIME() WHERE SceneDependencyID = @SceneDependencyID; END; GO CREATE OR ALTER PROCEDURE dbo.SceneDependency_ListByScene @SceneID int AS BEGIN SET NOCOUNT ON; SELECT sd.SceneDependencyID, sd.ProjectID, sd.SourceSceneID, sd.TargetSceneID, sd.SceneDependencyTypeID, sdt.TypeName AS SceneDependencyTypeName, sd.Description, sd.IsHardDependency, sd.CreatedDate, sd.UpdatedDate, sd.IsArchived, sourceOrder.BookID AS SourceBookID, sourceOrder.BookTitle AS SourceBookTitle, sourceOrder.ChapterID AS SourceChapterID, sourceOrder.ChapterNumber AS SourceChapterNumber, sourceOrder.SceneNumber AS SourceSceneNumber, sourceOrder.SceneTitle AS SourceSceneTitle, targetOrder.BookID AS TargetBookID, targetOrder.BookTitle AS TargetBookTitle, targetOrder.ChapterID AS TargetChapterID, targetOrder.ChapterNumber AS TargetChapterNumber, targetOrder.SceneNumber AS TargetSceneNumber, targetOrder.SceneTitle AS TargetSceneTitle, CASE WHEN sd.TargetSceneID = @SceneID THEN N'DependsOn' ELSE N'Dependent' END AS DependencyDirection FROM dbo.SceneDependencies sd INNER JOIN dbo.SceneDependencyTypes sdt ON sdt.SceneDependencyTypeID = sd.SceneDependencyTypeID INNER JOIN dbo.NarrativeSceneOrder sourceOrder ON sourceOrder.SceneID = sd.SourceSceneID INNER JOIN dbo.NarrativeSceneOrder targetOrder ON targetOrder.SceneID = sd.TargetSceneID WHERE sd.IsArchived = 0 AND @SceneID IN (sd.SourceSceneID, sd.TargetSceneID) ORDER BY DependencyDirection, sourceOrder.GlobalSceneIndex, targetOrder.GlobalSceneIndex; END; GO CREATE OR ALTER PROCEDURE dbo.SceneDependency_ListByProject @ProjectID int, @BookID int = NULL AS BEGIN SET NOCOUNT ON; SELECT sd.SceneDependencyID, sd.ProjectID, sd.SourceSceneID, sd.TargetSceneID, sd.SceneDependencyTypeID, sdt.TypeName AS SceneDependencyTypeName, sd.Description, sd.IsHardDependency, sd.CreatedDate, sd.UpdatedDate, sd.IsArchived, sourceOrder.BookID AS SourceBookID, sourceOrder.BookTitle AS SourceBookTitle, sourceOrder.ChapterID AS SourceChapterID, sourceOrder.ChapterNumber AS SourceChapterNumber, sourceOrder.SceneNumber AS SourceSceneNumber, sourceOrder.SceneTitle AS SourceSceneTitle, targetOrder.BookID AS TargetBookID, targetOrder.BookTitle AS TargetBookTitle, targetOrder.ChapterID AS TargetChapterID, targetOrder.ChapterNumber AS TargetChapterNumber, targetOrder.SceneNumber AS TargetSceneNumber, targetOrder.SceneTitle AS TargetSceneTitle FROM dbo.SceneDependencies sd INNER JOIN dbo.SceneDependencyTypes sdt ON sdt.SceneDependencyTypeID = sd.SceneDependencyTypeID INNER JOIN dbo.NarrativeSceneOrder sourceOrder ON sourceOrder.SceneID = sd.SourceSceneID INNER JOIN dbo.NarrativeSceneOrder targetOrder ON targetOrder.SceneID = sd.TargetSceneID WHERE sd.IsArchived = 0 AND sd.ProjectID = @ProjectID AND (@BookID IS NULL OR targetOrder.BookID = @BookID OR sourceOrder.BookID = @BookID) ORDER BY sourceOrder.GlobalSceneIndex, targetOrder.GlobalSceneIndex; END; GO CREATE OR ALTER PROCEDURE dbo.SceneDependency_Counts @ProjectID int, @BookID int = NULL AS BEGIN SET NOCOUNT ON; SELECT scene.SceneID, COUNT(*) AS DependencyCount FROM dbo.NarrativeSceneOrder scene INNER JOIN dbo.SceneDependencies sd ON scene.SceneID IN (sd.SourceSceneID, sd.TargetSceneID) AND sd.IsArchived = 0 WHERE scene.ProjectID = @ProjectID AND (@BookID IS NULL OR scene.BookID = @BookID) GROUP BY scene.SceneID; END; GO CREATE OR ALTER PROCEDURE dbo.ChapterOption_ListByProject @ProjectID int AS BEGIN SET NOCOUNT ON; SELECT c.ChapterID, b.BookID, b.BookTitle, b.BookNumber, c.ChapterNumber, c.ChapterTitle, c.SortOrder FROM dbo.Chapters c INNER JOIN dbo.Books b ON b.BookID = c.BookID WHERE b.ProjectID = @ProjectID AND b.IsArchived = 0 AND c.IsArchived = 0 ORDER BY b.SortOrder, b.BookNumber, c.SortOrder, c.ChapterNumber; END; GO CREATE OR ALTER PROCEDURE dbo.Scene_NormalizeSortOrder @ChapterID int AS BEGIN SET NOCOUNT ON; ;WITH ordered AS ( SELECT SceneID, ROW_NUMBER() OVER (ORDER BY SortOrder, SceneNumber, SceneID) AS rn FROM dbo.Scenes WHERE ChapterID = @ChapterID AND IsArchived = 0 ) UPDATE s SET SortOrder = ordered.rn * 10, UpdatedDate = SYSUTCDATETIME() FROM dbo.Scenes s INNER JOIN ordered ON ordered.SceneID = s.SceneID; END; GO CREATE OR ALTER PROCEDURE dbo.Scene_RenumberChapter @ChapterID int AS BEGIN SET NOCOUNT ON; ;WITH ordered AS ( SELECT SceneID, ROW_NUMBER() OVER (ORDER BY SortOrder, SceneNumber, SceneID) AS rn FROM dbo.Scenes WHERE ChapterID = @ChapterID AND IsArchived = 0 ) UPDATE s SET SceneNumber = ordered.rn, SortOrder = ordered.rn * 10, UpdatedDate = SYSUTCDATETIME() FROM dbo.Scenes s INNER JOIN ordered ON ordered.SceneID = s.SceneID; END; GO CREATE OR ALTER PROCEDURE dbo.Chapter_RenumberBook @BookID int AS BEGIN SET NOCOUNT ON; ;WITH ordered AS ( SELECT ChapterID, ROW_NUMBER() OVER (ORDER BY SortOrder, ChapterNumber, ChapterID) AS rn FROM dbo.Chapters WHERE BookID = @BookID AND IsArchived = 0 ) UPDATE c SET ChapterNumber = ordered.rn, SortOrder = ordered.rn * 10, UpdatedDate = SYSUTCDATETIME() FROM dbo.Chapters c INNER JOIN ordered ON ordered.ChapterID = c.ChapterID; END; GO CREATE OR ALTER PROCEDURE dbo.SceneMovePreview_Get @SceneID int, @TargetChapterID int, @Position nvarchar(20) = N'End' AS BEGIN SET NOCOUNT ON; SELECT s.SceneID, s.SceneNumber, s.SceneTitle, s.ChapterID AS SourceChapterID, sourceChapter.ChapterNumber AS SourceChapterNumber, sourceChapter.ChapterTitle AS SourceChapterTitle, sourceBook.BookID AS SourceBookID, sourceBook.BookTitle AS SourceBookTitle, @TargetChapterID AS TargetChapterID, targetChapter.ChapterNumber AS TargetChapterNumber, targetChapter.ChapterTitle AS TargetChapterTitle, targetBook.BookID AS TargetBookID, targetBook.BookTitle AS TargetBookTitle, @Position AS Position, (SELECT COUNT(*) FROM dbo.SceneDependencies WHERE IsArchived = 0 AND @SceneID IN (SourceSceneID, TargetSceneID)) AS DependencyCount, (SELECT COUNT(*) FROM dbo.ContinuityWarnings WHERE IsDismissed = 0 AND IsIntentional = 0 AND SceneID = @SceneID) AS ActiveWarningCount FROM dbo.Scenes s INNER JOIN dbo.Chapters sourceChapter ON sourceChapter.ChapterID = s.ChapterID INNER JOIN dbo.Books sourceBook ON sourceBook.BookID = sourceChapter.BookID INNER JOIN dbo.Chapters targetChapter ON targetChapter.ChapterID = @TargetChapterID INNER JOIN dbo.Books targetBook ON targetBook.BookID = targetChapter.BookID WHERE s.SceneID = @SceneID; END; GO CREATE OR ALTER PROCEDURE dbo.Scene_MoveToChapter @SceneID int, @TargetChapterID int, @Position nvarchar(20) = N'End', @Renumber bit = 0 AS BEGIN SET NOCOUNT ON; DECLARE @SourceChapterID int = (SELECT ChapterID FROM dbo.Scenes WHERE SceneID = @SceneID); DECLARE @NewSortOrder int; IF @Position = N'Start' SELECT @NewSortOrder = ISNULL(MIN(SortOrder), 10) - 5 FROM dbo.Scenes WHERE ChapterID = @TargetChapterID AND IsArchived = 0; ELSE SELECT @NewSortOrder = ISNULL(MAX(SortOrder), 0) + 10 FROM dbo.Scenes WHERE ChapterID = @TargetChapterID AND IsArchived = 0 AND SceneID <> @SceneID; UPDATE dbo.Scenes SET ChapterID = @TargetChapterID, SortOrder = @NewSortOrder, UpdatedDate = SYSUTCDATETIME() WHERE SceneID = @SceneID; EXEC dbo.Scene_NormalizeSortOrder @SourceChapterID; EXEC dbo.Scene_NormalizeSortOrder @TargetChapterID; IF @Renumber = 1 BEGIN EXEC dbo.Scene_RenumberChapter @SourceChapterID; EXEC dbo.Scene_RenumberChapter @TargetChapterID; END; SELECT @SceneID; END; GO CREATE OR ALTER PROCEDURE dbo.SceneDependency_FinaliseWarnings @ProjectID int, @BookID int = NULL AS BEGIN SET NOCOUNT ON; DECLARE @ErrorSeverityID int = (SELECT WarningSeverityID FROM dbo.WarningSeverities WHERE SeverityName = N'Error'); DECLARE @WarningSeverityID int = (SELECT WarningSeverityID FROM dbo.WarningSeverities WHERE SeverityName = N'Warning'); DECLARE @WarningTypeID int = (SELECT WarningTypeID FROM dbo.WarningTypes WHERE TypeName = N'Scene Dependency Broken'); UPDATE cw SET WarningSeverityID = CASE WHEN sd.IsHardDependency = 1 THEN @ErrorSeverityID ELSE @WarningSeverityID END, Message = CONCAT(N'Possible scene order issue: ''', sourceOrder.SceneTitle, N''' is now after ''', targetOrder.SceneTitle, N'''.'), Details = COALESCE(sd.Description, cw.Details), LastDetectedDate = SYSUTCDATETIME() FROM dbo.ContinuityWarnings cw INNER JOIN dbo.SceneDependencies sd ON sd.SceneDependencyID = cw.EntityID INNER JOIN dbo.NarrativeSceneOrder sourceOrder ON sourceOrder.SceneID = sd.SourceSceneID INNER JOIN dbo.NarrativeSceneOrder targetOrder ON targetOrder.SceneID = sd.TargetSceneID WHERE cw.ProjectID = @ProjectID AND cw.WarningTypeID = @WarningTypeID AND cw.EntityType = N'SceneDependency' AND (@BookID IS NULL OR cw.BookID = @BookID); END; GO