SET ANSI_NULLS ON; GO SET QUOTED_IDENTIFIER ON; GO CREATE OR ALTER PROCEDURE dbo.WordCompanion_Scene_Companion @SceneID int, @UserID int AS BEGIN SET NOCOUNT ON; DECLARE @ProjectID int; DECLARE @BookID int; SELECT @ProjectID = b.ProjectID, @BookID = b.BookID FROM dbo.Scenes s INNER JOIN dbo.Chapters c ON c.ChapterID = s.ChapterID INNER JOIN dbo.Books b ON b.BookID = c.BookID INNER JOIN dbo.Projects p ON p.ProjectID = b.ProjectID INNER JOIN dbo.ProjectUserAccess pua ON pua.ProjectID = p.ProjectID WHERE s.SceneID = @SceneID AND s.IsArchived = 0 AND c.IsArchived = 0 AND b.IsArchived = 0 AND p.IsArchived = 0 AND pua.UserID = @UserID AND pua.IsActive = 1; IF @ProjectID IS NULL RETURN; SELECT s.SceneID, c.ChapterID, c.ChapterTitle, s.SceneTitle, sw.ActualWordCount AS ActualWords, sw.EstimatedWordCount AS EstimatedWords, s.ScenePurposeNotes AS WritingBrief, COALESCE(sw.IsBlocked, 0) AS Blocked, sw.BlockedReason, s.PrimaryLocationID AS PrimaryLocationId FROM dbo.Scenes s INNER JOIN dbo.Chapters c ON c.ChapterID = s.ChapterID LEFT JOIN dbo.SceneWorkflow sw ON sw.SceneID = s.SceneID WHERE s.SceneID = @SceneID; SELECT ch.CharacterID, ch.CharacterName AS Name, CAST(CASE WHEN EXISTS (SELECT 1 FROM dbo.SceneCharacters sc WHERE sc.SceneID = @SceneID AND sc.CharacterID = ch.CharacterID) THEN 1 ELSE 0 END AS bit) AS Linked FROM dbo.Characters ch WHERE ch.ProjectID = @ProjectID AND ch.IsArchived = 0 ORDER BY ch.CharacterName, ch.CharacterID; SELECT sa.StoryAssetID AS AssetId, sa.AssetName AS Name, CAST(CASE WHEN EXISTS (SELECT 1 FROM dbo.AssetEvents ae WHERE ae.SceneID = @SceneID AND ae.StoryAssetID = sa.StoryAssetID) OR EXISTS (SELECT 1 FROM dbo.SceneAssetLocations sal WHERE sal.SceneID = @SceneID AND sal.StoryAssetID = sa.StoryAssetID) THEN 1 ELSE 0 END AS bit) AS Linked FROM dbo.StoryAssets sa WHERE sa.ProjectID = @ProjectID AND sa.IsArchived = 0 ORDER BY sa.AssetName, sa.StoryAssetID; SELECT l.LocationID, l.LocationName AS Name, CAST(CASE WHEN EXISTS (SELECT 1 FROM dbo.Scenes s WHERE s.SceneID = @SceneID AND s.PrimaryLocationID = l.LocationID) THEN 1 ELSE 0 END AS bit) AS Linked FROM dbo.Locations l WHERE l.ProjectID = @ProjectID AND l.IsArchived = 0 ORDER BY l.LocationName, l.LocationID; END; GO CREATE OR ALTER PROCEDURE dbo.WordCompanion_SceneLinks_Update @SceneID int, @UserID int, @CharacterIds nvarchar(max) = NULL, @AssetIds nvarchar(max) = NULL, @LocationIds nvarchar(max) = NULL, @PrimaryLocationId int = NULL AS BEGIN SET NOCOUNT ON; DECLARE @ProjectID int; DECLARE @UsedAssetEventTypeID int; 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 INNER JOIN dbo.Projects p ON p.ProjectID = b.ProjectID INNER JOIN dbo.ProjectUserAccess pua ON pua.ProjectID = p.ProjectID WHERE s.SceneID = @SceneID AND s.IsArchived = 0 AND c.IsArchived = 0 AND b.IsArchived = 0 AND p.IsArchived = 0 AND pua.UserID = @UserID AND pua.IsActive = 1; IF @ProjectID IS NULL RETURN; SELECT TOP (1) @UsedAssetEventTypeID = AssetEventTypeID FROM dbo.AssetEventTypes WHERE TypeName = N'Used' AND IsActive = 1 ORDER BY SortOrder, AssetEventTypeID; IF @UsedAssetEventTypeID IS NULL SELECT TOP (1) @UsedAssetEventTypeID = AssetEventTypeID FROM dbo.AssetEventTypes WHERE IsActive = 1 ORDER BY SortOrder, AssetEventTypeID; IF @UsedAssetEventTypeID IS NULL RETURN; DECLARE @Characters TABLE (ID int PRIMARY KEY); DECLARE @Assets TABLE (ID int PRIMARY KEY); INSERT @Characters (ID) SELECT DISTINCT TRY_CONVERT(int, LTRIM(RTRIM(value))) FROM STRING_SPLIT(ISNULL(@CharacterIds, N''), N',') WHERE NULLIF(LTRIM(RTRIM(value)), N'') IS NOT NULL AND TRY_CONVERT(int, LTRIM(RTRIM(value))) IS NOT NULL; INSERT @Assets (ID) SELECT DISTINCT TRY_CONVERT(int, LTRIM(RTRIM(value))) FROM STRING_SPLIT(ISNULL(@AssetIds, N''), N',') WHERE NULLIF(LTRIM(RTRIM(value)), N'') IS NOT NULL AND TRY_CONVERT(int, LTRIM(RTRIM(value))) IS NOT NULL; IF EXISTS (SELECT 1 FROM @Characters requested WHERE requested.ID <= 0 OR NOT EXISTS (SELECT 1 FROM dbo.Characters c WHERE c.CharacterID = requested.ID AND c.ProjectID = @ProjectID AND c.IsArchived = 0)) RETURN; IF EXISTS (SELECT 1 FROM @Assets requested WHERE requested.ID <= 0 OR NOT EXISTS (SELECT 1 FROM dbo.StoryAssets sa WHERE sa.StoryAssetID = requested.ID AND sa.ProjectID = @ProjectID AND sa.IsArchived = 0)) RETURN; IF @PrimaryLocationId IS NOT NULL AND NOT EXISTS (SELECT 1 FROM dbo.Locations l WHERE l.LocationID = @PrimaryLocationId AND l.ProjectID = @ProjectID AND l.IsArchived = 0) RETURN; UPDATE dbo.Scenes SET PrimaryLocationID = @PrimaryLocationId, UpdatedDate = SYSUTCDATETIME() WHERE SceneID = @SceneID; DELETE sc FROM dbo.SceneCharacters sc WHERE sc.SceneID = @SceneID AND NOT EXISTS (SELECT 1 FROM @Characters requested WHERE requested.ID = sc.CharacterID) AND sc.RoleInSceneTypeID IS NULL AND sc.PresenceTypeID IS NULL AND sc.LocationID IS NULL AND sc.EntryLocationID IS NULL AND sc.ExitLocationID IS NULL AND sc.AppearanceNotes IS NULL AND sc.OutfitDescription IS NULL AND sc.PhysicalCondition IS NULL AND sc.EmotionalState IS NULL AND sc.KnowledgeNotes IS NULL; INSERT dbo.SceneCharacters (SceneID, CharacterID) SELECT @SceneID, requested.ID FROM @Characters requested WHERE NOT EXISTS (SELECT 1 FROM dbo.SceneCharacters sc WHERE sc.SceneID = @SceneID AND sc.CharacterID = requested.ID); DELETE ae FROM dbo.AssetEvents ae WHERE ae.SceneID = @SceneID AND ae.AssetEventTypeID = @UsedAssetEventTypeID AND ae.EventTitle = N'Used' AND ae.EventDescription IS NULL AND ae.FromStateID IS NULL AND ae.ToStateID IS NULL AND NOT EXISTS (SELECT 1 FROM @Assets requested WHERE requested.ID = ae.StoryAssetID); DELETE sal FROM dbo.SceneAssetLocations sal WHERE sal.SceneID = @SceneID AND sal.Description IS NULL AND NOT EXISTS (SELECT 1 FROM @Assets requested WHERE requested.ID = sal.StoryAssetID); INSERT dbo.AssetEvents (StoryAssetID, SceneID, AssetEventTypeID, FromStateID, ToStateID, EventTitle, EventDescription) SELECT requested.ID, @SceneID, @UsedAssetEventTypeID, NULL, NULL, N'Used', NULL FROM @Assets requested WHERE NOT EXISTS (SELECT 1 FROM dbo.AssetEvents ae WHERE ae.SceneID = @SceneID AND ae.StoryAssetID = requested.ID) AND NOT EXISTS (SELECT 1 FROM dbo.SceneAssetLocations sal WHERE sal.SceneID = @SceneID AND sal.StoryAssetID = requested.ID); IF @PrimaryLocationId IS NOT NULL BEGIN INSERT dbo.SceneAssetLocations (SceneID, StoryAssetID, LocationID, Description) SELECT @SceneID, requested.ID, @PrimaryLocationId, NULL FROM @Assets requested WHERE NOT EXISTS (SELECT 1 FROM dbo.SceneAssetLocations sal WHERE sal.SceneID = @SceneID AND sal.StoryAssetID = requested.ID); UPDATE sal SET LocationID = @PrimaryLocationId, UpdatedDate = SYSUTCDATETIME() FROM dbo.SceneAssetLocations sal INNER JOIN @Assets requested ON requested.ID = sal.StoryAssetID WHERE sal.SceneID = @SceneID AND sal.Description IS NULL; END; SELECT @SceneID AS SceneId, (SELECT COUNT(*) FROM @Characters) AS CharactersUpdated, (SELECT COUNT(*) FROM @Assets) AS AssetsUpdated, CASE WHEN @PrimaryLocationId IS NULL THEN 0 ELSE 1 END AS LocationsUpdated, N'Scene links updated.' AS Message; END; GO