(self, validated_data)
| 560 | return StreamSerializer(ordered_streams, many=True).data |
| 561 | |
| 562 | def create(self, validated_data): |
| 563 | streams = validated_data.pop("streams", []) |
| 564 | override_data = validated_data.pop("override", None) |
| 565 | channel_number = validated_data.pop( |
| 566 | "channel_number", Channel.get_next_available_channel_number() |
| 567 | ) |
| 568 | validated_data["channel_number"] = channel_number |
| 569 | |
| 570 | # Auto-assign Default Group if no channel_group is specified |
| 571 | if "channel_group" not in validated_data or validated_data.get("channel_group") is None: |
| 572 | from apps.channels.models import ChannelGroup |
| 573 | default_group, _ = ChannelGroup.objects.get_or_create(name="Default Group") |
| 574 | validated_data["channel_group"] = default_group |
| 575 | |
| 576 | # Atomic wrapper keeps the channel insert and its override row |
| 577 | # in the same transaction so a failure on either rolls both back. |
| 578 | with transaction.atomic(): |
| 579 | channel = Channel.objects.create(**validated_data) |
| 580 | |
| 581 | # Add streams in the specified order |
| 582 | for index, stream in enumerate(streams): |
| 583 | ChannelStream.objects.create( |
| 584 | channel=channel, stream_id=stream.id, order=index |
| 585 | ) |
| 586 | |
| 587 | if override_data: |
| 588 | # Manual channels (auto_created=False) have no provider |
| 589 | # value to override; reject the override payload here so a |
| 590 | # programmatic client can't write a semantically meaningless |
| 591 | # row that the frontend would then surface as "Overrides |
| 592 | # active". |
| 593 | if not channel.auto_created: |
| 594 | raise serializers.ValidationError( |
| 595 | { |
| 596 | "override": ( |
| 597 | "Cannot set override on a manual channel; " |
| 598 | "overrides only apply to auto-created channels." |
| 599 | ) |
| 600 | } |
| 601 | ) |
| 602 | obj = ChannelOverride.objects.create(channel=channel, **override_data) |
| 603 | # Drop an all-null override row; an empty override would |
| 604 | # falsely surface as active in the UI. |
| 605 | if not obj.has_any_override(): |
| 606 | obj.delete() |
| 607 | |
| 608 | return channel |
| 609 | |
| 610 | def update(self, instance, validated_data): |
| 611 | """ |
nothing calls this directly
no test coverage detected