updates
This commit is contained in:
@@ -1,8 +1,11 @@
|
||||
from fastapi import APIRouter, Depends, HTTPException, status, Query, Request
|
||||
from fastapi import APIRouter, Depends, HTTPException, status, Query, Request, UploadFile, File
|
||||
from sqlalchemy.orm import Session, joinedload, load_only
|
||||
from sqlalchemy import and_, or_, func, desc
|
||||
from typing import List, Optional
|
||||
from datetime import datetime, timedelta
|
||||
from pathlib import Path
|
||||
import uuid
|
||||
import hashlib
|
||||
from ...shared.config.database import get_db
|
||||
from ...shared.config.logging_config import get_logger
|
||||
from ...security.middleware.auth import get_current_user, authorize_roles
|
||||
@@ -119,15 +122,23 @@ async def get_maintenance_records(
|
||||
):
|
||||
"""Get maintenance records with filtering"""
|
||||
try:
|
||||
# Check if user is staff (not admin) - staff should only see their assigned records
|
||||
# Check if user is staff (not admin) - staff should see their assigned records AND unassigned records
|
||||
role = db.query(Role).filter(Role.id == current_user.role_id).first()
|
||||
is_staff = role and role.name == 'staff'
|
||||
|
||||
query = db.query(RoomMaintenance)
|
||||
query = db.query(RoomMaintenance).options(
|
||||
joinedload(RoomMaintenance.room),
|
||||
joinedload(RoomMaintenance.assigned_staff)
|
||||
)
|
||||
|
||||
# Filter by assigned_to for staff users
|
||||
# Filter by assigned_to for staff users - include unassigned records so they can pick them up
|
||||
if is_staff:
|
||||
query = query.filter(RoomMaintenance.assigned_to == current_user.id)
|
||||
query = query.filter(
|
||||
or_(
|
||||
RoomMaintenance.assigned_to == current_user.id,
|
||||
RoomMaintenance.assigned_to.is_(None)
|
||||
)
|
||||
)
|
||||
|
||||
if room_id:
|
||||
query = query.filter(RoomMaintenance.room_id == room_id)
|
||||
@@ -144,6 +155,13 @@ async def get_maintenance_records(
|
||||
|
||||
result = []
|
||||
for record in records:
|
||||
# Get reported by user info
|
||||
reported_by_name = None
|
||||
if record.reported_by:
|
||||
reported_by_user = db.query(User).filter(User.id == record.reported_by).first()
|
||||
if reported_by_user:
|
||||
reported_by_name = reported_by_user.full_name
|
||||
|
||||
result.append({
|
||||
'id': record.id,
|
||||
'room_id': record.room_id,
|
||||
@@ -158,11 +176,16 @@ async def get_maintenance_records(
|
||||
'actual_end': record.actual_end.isoformat() if record.actual_end else None,
|
||||
'assigned_to': record.assigned_to,
|
||||
'assigned_staff_name': record.assigned_staff.full_name if record.assigned_staff else None,
|
||||
'reported_by': record.reported_by,
|
||||
'reported_by_name': reported_by_name,
|
||||
'priority': record.priority,
|
||||
'blocks_room': record.blocks_room,
|
||||
'estimated_cost': float(record.estimated_cost) if record.estimated_cost else None,
|
||||
'actual_cost': float(record.actual_cost) if record.actual_cost else None,
|
||||
'created_at': record.created_at.isoformat() if record.created_at else None
|
||||
'notes': record.notes,
|
||||
'completion_notes': record.completion_notes if hasattr(record, 'completion_notes') else None,
|
||||
'created_at': record.created_at.isoformat() if record.created_at else None,
|
||||
'updated_at': record.updated_at.isoformat() if record.updated_at else None,
|
||||
})
|
||||
|
||||
return {
|
||||
@@ -184,16 +207,34 @@ async def get_maintenance_records(
|
||||
@router.post('/maintenance')
|
||||
async def create_maintenance_record(
|
||||
maintenance_data: dict,
|
||||
current_user: User = Depends(authorize_roles('admin', 'staff')),
|
||||
current_user: User = Depends(authorize_roles('admin', 'staff', 'housekeeping')),
|
||||
db: Session = Depends(get_db)
|
||||
):
|
||||
"""Create a new maintenance record"""
|
||||
try:
|
||||
# Check user role - housekeeping users can only report issues, not create full maintenance records
|
||||
role = db.query(Role).filter(Role.id == current_user.role_id).first()
|
||||
is_housekeeping = role and role.name == 'housekeeping'
|
||||
|
||||
room = db.query(Room).filter(Room.id == maintenance_data.get('room_id')).first()
|
||||
if not room:
|
||||
raise HTTPException(status_code=404, detail='Room not found')
|
||||
|
||||
scheduled_start = datetime.fromisoformat(maintenance_data['scheduled_start'].replace('Z', '+00:00'))
|
||||
# For housekeeping users, set defaults for quick issue reporting
|
||||
if is_housekeeping:
|
||||
# Housekeeping users can only create corrective/emergency maintenance
|
||||
maintenance_type = maintenance_data.get('maintenance_type', 'corrective')
|
||||
if maintenance_type not in ['corrective', 'emergency']:
|
||||
maintenance_type = 'corrective'
|
||||
maintenance_data['maintenance_type'] = maintenance_type
|
||||
# Default to high priority for housekeeping-reported issues
|
||||
if 'priority' not in maintenance_data:
|
||||
maintenance_data['priority'] = 'high'
|
||||
# Default to blocking room
|
||||
if 'blocks_room' not in maintenance_data:
|
||||
maintenance_data['blocks_room'] = True
|
||||
|
||||
scheduled_start = datetime.fromisoformat(maintenance_data.get('scheduled_start', datetime.utcnow().isoformat()).replace('Z', '+00:00'))
|
||||
scheduled_end = None
|
||||
if maintenance_data.get('scheduled_end'):
|
||||
scheduled_end = datetime.fromisoformat(maintenance_data['scheduled_end'].replace('Z', '+00:00'))
|
||||
@@ -357,12 +398,13 @@ async def get_housekeeping_tasks(
|
||||
is_admin = role and role.name == 'admin'
|
||||
is_housekeeping_or_staff = role and role.name in ('housekeeping', 'staff')
|
||||
|
||||
query = db.query(HousekeepingTask)
|
||||
# Build base query for filtering
|
||||
base_query = db.query(HousekeepingTask)
|
||||
|
||||
# Filter by assigned_to for housekeeping and staff users (not admin)
|
||||
# But also include unassigned tasks so they can pick them up
|
||||
if is_housekeeping_or_staff:
|
||||
query = query.filter(
|
||||
base_query = base_query.filter(
|
||||
or_(
|
||||
HousekeepingTask.assigned_to == current_user.id,
|
||||
HousekeepingTask.assigned_to.is_(None)
|
||||
@@ -370,17 +412,31 @@ async def get_housekeeping_tasks(
|
||||
)
|
||||
|
||||
if room_id:
|
||||
query = query.filter(HousekeepingTask.room_id == room_id)
|
||||
base_query = base_query.filter(HousekeepingTask.room_id == room_id)
|
||||
if status:
|
||||
query = query.filter(HousekeepingTask.status == HousekeepingStatus(status))
|
||||
base_query = base_query.filter(HousekeepingTask.status == HousekeepingStatus(status))
|
||||
if task_type:
|
||||
query = query.filter(HousekeepingTask.task_type == HousekeepingType(task_type))
|
||||
base_query = base_query.filter(HousekeepingTask.task_type == HousekeepingType(task_type))
|
||||
if date:
|
||||
date_obj = datetime.fromisoformat(date.replace('Z', '+00:00')).date()
|
||||
query = query.filter(func.date(HousekeepingTask.scheduled_time) == date_obj)
|
||||
try:
|
||||
# Handle different date formats
|
||||
if 'T' in date:
|
||||
date_obj = datetime.fromisoformat(date.replace('Z', '+00:00')).date()
|
||||
else:
|
||||
date_obj = datetime.strptime(date, '%Y-%m-%d').date()
|
||||
base_query = base_query.filter(func.date(HousekeepingTask.scheduled_time) == date_obj)
|
||||
except (ValueError, AttributeError) as date_error:
|
||||
logger.error(f'Error parsing date {date}: {str(date_error)}')
|
||||
raise HTTPException(status_code=400, detail=f'Invalid date format: {date}')
|
||||
|
||||
total = query.count()
|
||||
query = query.order_by(HousekeepingTask.scheduled_time)
|
||||
# Get count before adding joins (to avoid duplicate counting)
|
||||
total = base_query.count()
|
||||
|
||||
# Add eager loading and ordering for the actual data query
|
||||
query = base_query.options(
|
||||
joinedload(HousekeepingTask.room),
|
||||
joinedload(HousekeepingTask.assigned_staff)
|
||||
).order_by(HousekeepingTask.scheduled_time)
|
||||
|
||||
offset = (page - 1) * limit
|
||||
tasks = query.offset(offset).limit(limit).all()
|
||||
@@ -390,26 +446,43 @@ async def get_housekeeping_tasks(
|
||||
|
||||
# Process existing tasks
|
||||
for task in tasks:
|
||||
task_room_ids.add(task.room_id)
|
||||
result.append({
|
||||
'id': task.id,
|
||||
'room_id': task.room_id,
|
||||
'room_number': task.room.room_number if task.room else None,
|
||||
'booking_id': task.booking_id,
|
||||
'task_type': task.task_type.value,
|
||||
'status': task.status.value,
|
||||
'scheduled_time': task.scheduled_time.isoformat() if task.scheduled_time else None,
|
||||
'started_at': task.started_at.isoformat() if task.started_at else None,
|
||||
'completed_at': task.completed_at.isoformat() if task.completed_at else None,
|
||||
'assigned_to': task.assigned_to,
|
||||
'assigned_staff_name': task.assigned_staff.full_name if task.assigned_staff else None,
|
||||
'checklist_items': task.checklist_items,
|
||||
'notes': task.notes,
|
||||
'quality_score': task.quality_score,
|
||||
'estimated_duration_minutes': task.estimated_duration_minutes,
|
||||
'actual_duration_minutes': task.actual_duration_minutes,
|
||||
'room_status': task.room.status.value if task.room else None
|
||||
})
|
||||
try:
|
||||
task_room_ids.add(task.room_id)
|
||||
|
||||
# Safely get room status
|
||||
room_status = None
|
||||
if task.room and hasattr(task.room, 'status') and task.room.status:
|
||||
room_status = task.room.status.value if hasattr(task.room.status, 'value') else str(task.room.status)
|
||||
|
||||
# Safely get assigned staff name
|
||||
assigned_staff_name = None
|
||||
if task.assigned_staff and hasattr(task.assigned_staff, 'full_name'):
|
||||
assigned_staff_name = task.assigned_staff.full_name
|
||||
|
||||
result.append({
|
||||
'id': task.id,
|
||||
'room_id': task.room_id,
|
||||
'room_number': task.room.room_number if task.room and hasattr(task.room, 'room_number') else None,
|
||||
'booking_id': task.booking_id,
|
||||
'task_type': task.task_type.value if hasattr(task.task_type, 'value') else str(task.task_type),
|
||||
'status': task.status.value if hasattr(task.status, 'value') else str(task.status),
|
||||
'scheduled_time': task.scheduled_time.isoformat() if task.scheduled_time else None,
|
||||
'started_at': task.started_at.isoformat() if task.started_at else None,
|
||||
'completed_at': task.completed_at.isoformat() if task.completed_at else None,
|
||||
'assigned_to': task.assigned_to,
|
||||
'assigned_staff_name': assigned_staff_name,
|
||||
'checklist_items': task.checklist_items if task.checklist_items else [],
|
||||
'notes': task.notes,
|
||||
'quality_score': task.quality_score,
|
||||
'estimated_duration_minutes': task.estimated_duration_minutes,
|
||||
'actual_duration_minutes': task.actual_duration_minutes,
|
||||
'room_status': room_status,
|
||||
'photos': task.photos if task.photos else []
|
||||
})
|
||||
except Exception as task_error:
|
||||
logger.error(f'Error processing task {task.id if task else "unknown"}: {str(task_error)}', exc_info=True)
|
||||
# Continue with next task instead of failing completely
|
||||
continue
|
||||
|
||||
# Include rooms in cleaning status that don't have tasks (or have unassigned tasks for housekeeping users)
|
||||
if include_cleaning_rooms:
|
||||
@@ -478,7 +551,8 @@ async def get_housekeeping_tasks(
|
||||
'estimated_duration_minutes': None,
|
||||
'actual_duration_minutes': None,
|
||||
'room_status': room.status.value,
|
||||
'is_room_status_only': True # Flag to indicate this is from room status, not a task
|
||||
'is_room_status_only': True, # Flag to indicate this is from room status, not a task
|
||||
'photos': []
|
||||
})
|
||||
|
||||
# Update total count to include cleaning rooms
|
||||
@@ -498,7 +572,8 @@ async def get_housekeeping_tasks(
|
||||
}
|
||||
}
|
||||
except Exception as e:
|
||||
raise HTTPException(status_code=500, detail=str(e))
|
||||
logger.error(f'Error fetching housekeeping tasks: {str(e)}', exc_info=True)
|
||||
raise HTTPException(status_code=500, detail='Failed to fetch housekeeping tasks')
|
||||
|
||||
|
||||
@router.post('/housekeeping')
|
||||
@@ -709,6 +784,8 @@ async def update_housekeeping_task(
|
||||
task.inspected_at = datetime.utcnow()
|
||||
if 'inspection_notes' in task_data:
|
||||
task.inspection_notes = task_data['inspection_notes']
|
||||
if 'photos' in task_data:
|
||||
task.photos = task_data['photos']
|
||||
|
||||
db.commit()
|
||||
db.refresh(task)
|
||||
@@ -746,6 +823,177 @@ async def update_housekeeping_task(
|
||||
raise HTTPException(status_code=500, detail=str(e))
|
||||
|
||||
|
||||
@router.post('/housekeeping/{task_id}/upload-photo')
|
||||
async def upload_housekeeping_task_photo(
|
||||
task_id: int,
|
||||
request: Request,
|
||||
image: UploadFile = File(...),
|
||||
current_user: User = Depends(authorize_roles('admin', 'staff', 'housekeeping')),
|
||||
db: Session = Depends(get_db)
|
||||
):
|
||||
"""Upload a photo for a housekeeping task"""
|
||||
try:
|
||||
task = db.query(HousekeepingTask).filter(HousekeepingTask.id == task_id).first()
|
||||
if not task:
|
||||
raise HTTPException(status_code=404, detail='Housekeeping task not found')
|
||||
|
||||
# Check permissions - housekeeping users can only upload photos to their assigned tasks
|
||||
role = db.query(Role).filter(Role.id == current_user.role_id).first()
|
||||
is_housekeeping_or_staff = role and role.name in ('housekeeping', 'staff')
|
||||
|
||||
if is_housekeeping_or_staff:
|
||||
if task.assigned_to != current_user.id:
|
||||
raise HTTPException(status_code=403, detail='You can only upload photos to tasks assigned to you')
|
||||
|
||||
# Validate and process image
|
||||
from ...shared.utils.file_validation import validate_uploaded_image
|
||||
from ...shared.config.settings import settings
|
||||
from PIL import Image
|
||||
import io
|
||||
|
||||
max_size = 5 * 1024 * 1024 # 5MB
|
||||
content = await validate_uploaded_image(image, max_size)
|
||||
|
||||
# Optimize image
|
||||
img = Image.open(io.BytesIO(content))
|
||||
if img.mode in ('RGBA', 'LA', 'P'):
|
||||
img = img.convert('RGB')
|
||||
|
||||
# Generate unique filename
|
||||
file_ext = Path(image.filename).suffix.lower() if image.filename else '.jpg'
|
||||
if file_ext not in ['.jpg', '.jpeg', '.png', '.webp']:
|
||||
file_ext = '.jpg'
|
||||
|
||||
filename = f"housekeeping_task_{task_id}_{uuid.uuid4().hex[:8]}{file_ext}"
|
||||
upload_dir = Path(__file__).parent.parent.parent.parent / 'uploads' / 'housekeeping'
|
||||
upload_dir.mkdir(parents=True, exist_ok=True)
|
||||
|
||||
file_path = upload_dir / filename
|
||||
|
||||
# Save optimized image
|
||||
img.save(file_path, 'JPEG', quality=85, optimize=True)
|
||||
|
||||
image_url = f'/uploads/housekeeping/{filename}'
|
||||
|
||||
# Update task photos
|
||||
if task.photos is None:
|
||||
task.photos = []
|
||||
if not isinstance(task.photos, list):
|
||||
task.photos = []
|
||||
|
||||
task.photos.append(image_url)
|
||||
db.commit()
|
||||
|
||||
# Get full URL
|
||||
base_url = str(request.base_url).rstrip('/')
|
||||
full_url = f"{base_url}{image_url}"
|
||||
|
||||
return {
|
||||
'status': 'success',
|
||||
'message': 'Photo uploaded successfully',
|
||||
'data': {
|
||||
'photo_url': image_url,
|
||||
'full_url': full_url,
|
||||
'photos': task.photos
|
||||
}
|
||||
}
|
||||
except HTTPException:
|
||||
raise
|
||||
except Exception as e:
|
||||
db.rollback()
|
||||
logger.error(f'Error uploading housekeeping task photo: {str(e)}', exc_info=True)
|
||||
raise HTTPException(status_code=500, detail=f'Error uploading photo: {str(e)}')
|
||||
|
||||
|
||||
@router.post('/housekeeping/{task_id}/report-maintenance-issue')
|
||||
async def report_maintenance_issue_from_task(
|
||||
task_id: int,
|
||||
issue_data: dict,
|
||||
current_user: User = Depends(authorize_roles('admin', 'staff', 'housekeeping')),
|
||||
db: Session = Depends(get_db)
|
||||
):
|
||||
"""Quick maintenance issue reporting from housekeeping task"""
|
||||
try:
|
||||
task = db.query(HousekeepingTask).filter(HousekeepingTask.id == task_id).first()
|
||||
if not task:
|
||||
raise HTTPException(status_code=404, detail='Housekeeping task not found')
|
||||
|
||||
# Check permissions - housekeeping users can only report issues for their assigned tasks
|
||||
role = db.query(Role).filter(Role.id == current_user.role_id).first()
|
||||
is_housekeeping = role and role.name == 'housekeeping'
|
||||
|
||||
if is_housekeeping:
|
||||
if task.assigned_to != current_user.id:
|
||||
raise HTTPException(status_code=403, detail='You can only report issues for tasks assigned to you')
|
||||
|
||||
room = db.query(Room).filter(Room.id == task.room_id).first()
|
||||
if not room:
|
||||
raise HTTPException(status_code=404, detail='Room not found')
|
||||
|
||||
# Create maintenance record
|
||||
title = issue_data.get('title', f'Issue reported from Room {room.room_number}')
|
||||
description = issue_data.get('description', '')
|
||||
if task.notes:
|
||||
description = f"Reported from housekeeping task.\n\nTask Notes: {task.notes}\n\nIssue Description: {description}".strip()
|
||||
else:
|
||||
description = f"Reported from housekeeping task.\n\nIssue Description: {description}".strip()
|
||||
|
||||
maintenance = RoomMaintenance(
|
||||
room_id=task.room_id,
|
||||
maintenance_type=MaintenanceType(issue_data.get('maintenance_type', 'corrective')),
|
||||
status=MaintenanceStatus('scheduled'),
|
||||
title=title,
|
||||
description=description,
|
||||
scheduled_start=datetime.utcnow(),
|
||||
assigned_to=None, # Will be assigned by admin/staff
|
||||
reported_by=current_user.id,
|
||||
priority=issue_data.get('priority', 'high'),
|
||||
blocks_room=issue_data.get('blocks_room', True),
|
||||
notes=issue_data.get('notes', f'Reported from housekeeping task #{task_id}')
|
||||
)
|
||||
|
||||
# Update room status if blocking
|
||||
if maintenance.blocks_room and room.status == RoomStatus.available:
|
||||
room.status = RoomStatus.maintenance
|
||||
|
||||
db.add(maintenance)
|
||||
db.commit()
|
||||
db.refresh(maintenance)
|
||||
|
||||
# Send notification to admin/staff
|
||||
try:
|
||||
from ...notifications.routes.notification_routes import notification_manager
|
||||
notification_data = {
|
||||
'type': 'maintenance_request_created',
|
||||
'data': {
|
||||
'maintenance_id': maintenance.id,
|
||||
'room_id': room.id,
|
||||
'room_number': room.room_number,
|
||||
'title': maintenance.title,
|
||||
'priority': maintenance.priority,
|
||||
'reported_by': current_user.full_name,
|
||||
'reported_at': maintenance.created_at.isoformat() if maintenance.created_at else None
|
||||
}
|
||||
}
|
||||
# Send to admin and staff roles
|
||||
await notification_manager.send_to_role('admin', notification_data)
|
||||
await notification_manager.send_to_role('staff', notification_data)
|
||||
except Exception as e:
|
||||
logger.error(f'Error sending maintenance notification: {str(e)}', exc_info=True)
|
||||
|
||||
return {
|
||||
'status': 'success',
|
||||
'message': 'Maintenance issue reported successfully',
|
||||
'data': {'maintenance_id': maintenance.id}
|
||||
}
|
||||
except HTTPException:
|
||||
raise
|
||||
except Exception as e:
|
||||
db.rollback()
|
||||
logger.error(f'Error reporting maintenance issue: {str(e)}', exc_info=True)
|
||||
raise HTTPException(status_code=500, detail=f'Error reporting issue: {str(e)}')
|
||||
|
||||
|
||||
# ==================== Room Inspections ====================
|
||||
|
||||
@router.get('/inspections')
|
||||
@@ -755,19 +1003,19 @@ async def get_room_inspections(
|
||||
status: Optional[str] = Query(None),
|
||||
page: int = Query(1, ge=1),
|
||||
limit: int = Query(20, ge=1, le=100),
|
||||
current_user: User = Depends(authorize_roles('admin', 'staff')),
|
||||
current_user: User = Depends(authorize_roles('admin', 'staff', 'housekeeping')),
|
||||
db: Session = Depends(get_db)
|
||||
):
|
||||
"""Get room inspections with filtering"""
|
||||
try:
|
||||
# Check if user is staff (not admin) - staff should only see their assigned inspections
|
||||
# Check if user is staff or housekeeping (not admin) - they should only see their assigned inspections
|
||||
role = db.query(Role).filter(Role.id == current_user.role_id).first()
|
||||
is_staff = role and role.name == 'staff'
|
||||
is_staff_or_housekeeping = role and role.name in ('staff', 'housekeeping')
|
||||
|
||||
query = db.query(RoomInspection)
|
||||
|
||||
# Filter by inspected_by for staff users
|
||||
if is_staff:
|
||||
# Filter by inspected_by for staff and housekeeping users
|
||||
if is_staff_or_housekeeping:
|
||||
query = query.filter(RoomInspection.inspected_by == current_user.id)
|
||||
|
||||
if room_id:
|
||||
@@ -824,16 +1072,27 @@ async def get_room_inspections(
|
||||
@router.post('/inspections')
|
||||
async def create_room_inspection(
|
||||
inspection_data: dict,
|
||||
current_user: User = Depends(authorize_roles('admin', 'staff')),
|
||||
current_user: User = Depends(authorize_roles('admin', 'staff', 'housekeeping')),
|
||||
db: Session = Depends(get_db)
|
||||
):
|
||||
"""Create a new room inspection"""
|
||||
try:
|
||||
# Check user role - housekeeping users can only create inspections for themselves
|
||||
role = db.query(Role).filter(Role.id == current_user.role_id).first()
|
||||
is_housekeeping = role and role.name == 'housekeeping'
|
||||
|
||||
room = db.query(Room).filter(Room.id == inspection_data.get('room_id')).first()
|
||||
if not room:
|
||||
raise HTTPException(status_code=404, detail='Room not found')
|
||||
|
||||
scheduled_at = datetime.fromisoformat(inspection_data['scheduled_at'].replace('Z', '+00:00'))
|
||||
inspected_by = inspection_data.get('inspected_by')
|
||||
|
||||
# Housekeeping users can only assign inspections to themselves
|
||||
if is_housekeeping:
|
||||
if inspected_by and inspected_by != current_user.id:
|
||||
raise HTTPException(status_code=403, detail='Housekeeping users can only create inspections for themselves')
|
||||
inspected_by = current_user.id
|
||||
|
||||
inspection = RoomInspection(
|
||||
room_id=inspection_data['room_id'],
|
||||
@@ -841,7 +1100,7 @@ async def create_room_inspection(
|
||||
inspection_type=InspectionType(inspection_data.get('inspection_type', 'routine')),
|
||||
status=InspectionStatus(inspection_data.get('status', 'pending')),
|
||||
scheduled_at=scheduled_at,
|
||||
inspected_by=inspection_data.get('inspected_by'),
|
||||
inspected_by=inspected_by,
|
||||
created_by=current_user.id,
|
||||
checklist_items=inspection_data.get('checklist_items', []),
|
||||
checklist_template_id=inspection_data.get('checklist_template_id')
|
||||
@@ -865,7 +1124,7 @@ async def create_room_inspection(
|
||||
async def update_room_inspection(
|
||||
inspection_id: int,
|
||||
inspection_data: dict,
|
||||
current_user: User = Depends(authorize_roles('admin', 'staff')),
|
||||
current_user: User = Depends(authorize_roles('admin', 'staff', 'housekeeping')),
|
||||
db: Session = Depends(get_db)
|
||||
):
|
||||
"""Update a room inspection"""
|
||||
@@ -874,16 +1133,16 @@ async def update_room_inspection(
|
||||
if not inspection:
|
||||
raise HTTPException(status_code=404, detail='Room inspection not found')
|
||||
|
||||
# Check if user is staff (not admin) - staff can only update their own assigned inspections
|
||||
# Check if user is staff or housekeeping (not admin) - they can only update their own assigned inspections
|
||||
role = db.query(Role).filter(Role.id == current_user.role_id).first()
|
||||
is_staff = role and role.name == 'staff'
|
||||
is_staff_or_housekeeping = role and role.name in ('staff', 'housekeeping')
|
||||
|
||||
if is_staff:
|
||||
# Staff can only update inspections assigned to them
|
||||
if is_staff_or_housekeeping:
|
||||
# Staff and housekeeping can only update inspections assigned to them
|
||||
if inspection.inspected_by != current_user.id:
|
||||
raise HTTPException(status_code=403, detail='You can only update inspections assigned to you')
|
||||
# Staff can only update status and inspection results
|
||||
allowed_fields = {'status', 'checklist_items', 'overall_score', 'overall_notes', 'issues_found', 'requires_followup', 'followup_notes'}
|
||||
# Staff and housekeeping can only update status and inspection results
|
||||
allowed_fields = {'status', 'checklist_items', 'overall_score', 'overall_notes', 'issues_found', 'requires_followup', 'followup_notes', 'photos'}
|
||||
if any(key not in allowed_fields for key in inspection_data.keys()):
|
||||
raise HTTPException(status_code=403, detail='You can only update status and inspection results')
|
||||
|
||||
|
||||
Reference in New Issue
Block a user