Files
Ske_Signage/app/utils/group_management.py
2025-07-16 08:03:57 +03:00

325 lines
8.7 KiB
Python

"""
Group management utilities
"""
from app.extensions import db
from app.models.group import Group
from app.models.player import Player
from app.models.content import Content
from app.utils.logger import log_group_created, log_group_edited, log_group_deleted, log_content_reordered
def create_group(name, player_ids=None, description=None):
"""
Create a new group
Args:
name (str): Group name
player_ids (list): List of player IDs to add to group (optional)
description (str): Group description (optional)
Returns:
tuple: (success, group_or_error_message)
"""
try:
# Check if group name already exists
if Group.query.filter_by(name=name).first():
return False, f"Group with name '{name}' already exists"
# Create new group
group = Group(
name=name,
description=description or ""
)
# Add players to group
if player_ids:
players = Player.query.filter(Player.id.in_(player_ids)).all()
for player in players:
group.players.append(player)
db.session.add(group)
db.session.commit()
log_group_created(name)
return True, group
except Exception as e:
db.session.rollback()
return False, str(e)
def edit_group(group_id, name=None, player_ids=None, description=None):
"""
Edit an existing group
Args:
group_id (int): Group ID
name (str): New group name (optional)
player_ids (list): New list of player IDs (optional)
description (str): New description (optional)
Returns:
tuple: (success, group_or_error_message)
"""
try:
group = Group.query.get(group_id)
if not group:
return False, "Group not found"
# Check for name conflicts
if name and name != group.name:
existing = Group.query.filter_by(name=name).first()
if existing and existing.id != group_id:
return False, f"Group with name '{name}' already exists"
group.name = name
# Update description
if description is not None:
group.description = description
# Update players
if player_ids is not None:
# Clear current players
group.players.clear()
# Add new players
if player_ids:
players = Player.query.filter(Player.id.in_(player_ids)).all()
for player in players:
group.players.append(player)
db.session.commit()
log_group_edited(group.name)
return True, group
except Exception as e:
db.session.rollback()
return False, str(e)
def delete_group(group_id):
"""
Delete a group (players remain, just removed from group)
Args:
group_id (int): Group ID
Returns:
tuple: (success, error_message)
"""
try:
group = Group.query.get(group_id)
if not group:
return False, "Group not found"
group_name = group.name
# Remove all players from group
group.players.clear()
# Delete group
db.session.delete(group)
db.session.commit()
log_group_deleted(group_name)
return True, None
except Exception as e:
db.session.rollback()
return False, str(e)
def get_group_content(group_id):
"""
Get all unique content for players in a group
Args:
group_id (int): Group ID
Returns:
list: List of Content objects
"""
group = Group.query.get(group_id)
if not group:
return []
player_ids = [player.id for player in group.players]
if not player_ids:
return []
# Get unique content by filename, taking the first occurrence
content_query = (
db.session.query(
Content.file_name,
db.func.min(Content.id).label('id'),
db.func.min(Content.duration).label('duration'),
db.func.min(Content.position).label('position')
)
.filter(Content.player_id.in_(player_ids))
.group_by(Content.file_name)
)
# Get the actual content objects
content_ids = [c.id for c in content_query.all()]
content = Content.query.filter(Content.id.in_(content_ids)).order_by(Content.position).all()
return content
def update_group_content_order(group_id, content_items):
"""
Update the order of content items for all players in a group
Args:
group_id (int): Group ID
content_items (list): List of content items with new positions
Returns:
tuple: (success, error_message)
"""
try:
group = Group.query.get(group_id)
if not group:
return False, "Group not found"
player_ids = [player.id for player in group.players]
if not player_ids:
return True, None # No players in group
# Update positions for all matching content across all players
for i, item in enumerate(content_items):
file_name = item.get('file_name')
if file_name:
Content.query.filter(
Content.player_id.in_(player_ids),
Content.file_name == file_name
).update({Content.position: i})
# Increment playlist version for all players and group
group.increment_playlist_version()
db.session.commit()
log_content_reordered('group', group.name)
return True, None
except Exception as e:
db.session.rollback()
return False, str(e)
def add_player_to_group(group_id, player_id):
"""
Add a player to a group
Args:
group_id (int): Group ID
player_id (int): Player ID
Returns:
tuple: (success, error_message)
"""
try:
group = Group.query.get(group_id)
player = Player.query.get(player_id)
if not group:
return False, "Group not found"
if not player:
return False, "Player not found"
if player not in group.players:
group.players.append(player)
db.session.commit()
return True, None
except Exception as e:
db.session.rollback()
return False, str(e)
def remove_player_from_group(group_id, player_id):
"""
Remove a player from a group
Args:
group_id (int): Group ID
player_id (int): Player ID
Returns:
tuple: (success, error_message)
"""
try:
group = Group.query.get(group_id)
player = Player.query.get(player_id)
if not group:
return False, "Group not found"
if not player:
return False, "Player not found"
if player in group.players:
group.players.remove(player)
db.session.commit()
return True, None
except Exception as e:
db.session.rollback()
return False, str(e)
def get_available_players():
"""
Get all players that are not locked to any group
Returns:
list: List of Player objects
"""
return Player.query.filter_by(locked_to_group_id=None).all()
def lock_players_to_group(group_id, player_ids):
"""
Lock specified players to a group (exclusive membership)
Args:
group_id (int): Group ID
player_ids (list): List of player IDs to lock
Returns:
tuple: (success, error_message)
"""
try:
group = Group.query.get(group_id)
if not group:
return False, "Group not found"
players = Player.query.filter(Player.id.in_(player_ids)).all()
for player in players:
player.locked_to_group_id = group_id
db.session.commit()
return True, None
except Exception as e:
db.session.rollback()
return False, str(e)
def unlock_players_from_group(group_id):
"""
Unlock all players from a group
Args:
group_id (int): Group ID
Returns:
tuple: (success, error_message)
"""
try:
players = Player.query.filter_by(locked_to_group_id=group_id).all()
for player in players:
player.locked_to_group_id = None
db.session.commit()
return True, None
except Exception as e:
db.session.rollback()
return False, str(e)