@@ -439,6 +439,19 @@ class IngestServerAPI implements IngestRestAPI {
439439 return ClientAPI . responseSuccess ( rundown )
440440 }
441441
442+ /**
443+ * Create a rundown through the REST ingest API.
444+ *
445+ * Note about playlist handling:
446+ *
447+ * Rundowns in Sofie are not owned by playlists. A playlist is merely a container
448+ * that may group multiple rundowns, and a rundown may move between playlists or
449+ * exist without an explicitly defined playlist.
450+ *
451+ * For this reason we intentionally do NOT include the playlistId when checking
452+ * if a rundown already exists. The `externalId` of a rundown is expected to be
453+ * unique within a studio, regardless of which playlist it belongs to.
454+ */
442455 async postRundown (
443456 _connection : Meteor . Connection ,
444457 _event : string ,
@@ -455,16 +468,16 @@ class IngestServerAPI implements IngestRestAPI {
455468 this . validateRundown ( ingestRundown )
456469 await this . validateAPIPayloadsForRundown ( studio . blueprintId , ingestRundown )
457470
471+ // IMPORTANT: Do not scope rundown existence checks by playlistId.
472+ // Rundowns are unique per studio, not per playlist.
458473 const existingRundown = await Rundowns . findOneAsync ( {
459474 $or : [
460475 {
461476 _id : protectString < RundownId > ( ingestRundown . externalId ) ,
462- playlistId : protectString < RundownPlaylistId > ( playlistId ) ,
463477 studioId : studio . _id ,
464478 } ,
465479 {
466480 externalId : ingestRundown . externalId ,
467- playlistExternalId : playlistId ,
468481 studioId : studio . _id ,
469482 } ,
470483 ] ,
0 commit comments