"""Split utils.""" from collaborator.constants import error from collaborator.constants.split_type import SplitTypeId from collaborator.models.rds.collaborator_persister import CollaboratorPersister from collaborator.models.rds.split import Split from collaborator.schemas.split import ( ReplacementSplitsSchema, ) from collaborator.utils import logging from collaborator.utils.error import OwsError from collaborator.utils.typing import User def get_collabs_needing_tcs_agreement(collab_ids: list[int]) -> list[int]: """Check if the new splits require Terms and Conditions agreement. Args: diff (ReplacementSplitDiff): The diff of the splits. Returns: bool: True if any of the affected collaborators have DP turned on """ collaborators_with_modified_splits = CollaboratorPersister.get_by_ids( list(collab_ids), throw_if_not_found=False, ) collabs_needing_tcs_agreement = [ collaborator["id"] for collaborator in collaborators_with_modified_splits if collaborator.get("dp_enabled_date") is not None ] return collabs_needing_tcs_agreement def filter_replacement_splits_by_type( replacements: list[ReplacementSplitsSchema], split_type: SplitTypeId, ) -> list[ReplacementSplitsSchema]: """Filter replacement splits by split type.""" return [ replacement_split for replacement_split in replacements if replacement_split.split_type_id == split_type ] def validate_split_rates(replacements: list[ReplacementSplitsSchema]): """Validate new split rates.""" # TODO: Determine how subaccount split rate validation interacts with # track split rate validation. # Also why don't we run the other track split rate validations here? # Namely no gross splits, no single net split > 100%, etc. # Assert no subaccount split is over 100% replacement_subaccount_splits = filter_replacement_splits_by_type( replacements, SplitTypeId.SUBACCOUNT ) if any( split.split_rate > 1 for replacement in replacement_subaccount_splits for split in replacement.splits ): raise OwsError( code=error.ERROR_CODE_BAD_PARAMS, message=error.ERROR_MESSAGE_SPLIT_PERCENTAGE_OVER_100, ) # Assert new track split total is <= 100% replacement_track_splits = filter_replacement_splits_by_type( replacements, SplitTypeId.TRACK ) track_splits_by_tuid: dict[str, list[ReplacementSplitsSchema]] = {} for split in replacement_track_splits: track_splits_by_tuid.setdefault(split.identifier, []).append(split) for splits in track_splits_by_tuid.values(): split_rate_total = sum( split.split_rate for replacement in splits for split in replacement.splits ) if split_rate_total > 1: raise OwsError( code=error.ERROR_CODE_BAD_PARAMS, message=error.ERROR_MESSAGE_SPLIT_PERCENTAGE_OVER_100, ) def log_upsert_events(splits: list[Split], user: User) -> None: """Log events for the inserted or updated splits.""" event_data = [ { "id": split.split_id, "original": next( s.to_dict() for s in splits if s.split_id == split.split_id ), "updated": split.to_dict(), } for split in splits ] logging.bulk_log_events(logging.LOG_EVENT_UPDATE, "split", event_data, user)