Prevent task starting and completion without assigned it staff

This commit is contained in:
Marc Rejohn Castillano 2026-03-02 20:22:42 +08:00
parent 43d2bd4f95
commit eb49329b16
2 changed files with 42 additions and 6 deletions

View File

@ -1102,6 +1102,36 @@ class TasksController {
} }
if (status == 'completed') { if (status == 'completed') {
// Check for IT staff assignment
final assignmentRows = await _client
.from('task_assignments')
.select('user_id')
.eq('task_id', taskId);
final assignedUserIds = (assignmentRows as List)
.map((row) => row['user_id']?.toString())
.whereType<String>()
.where((id) => id.isNotEmpty)
.toSet()
.toList();
if (assignedUserIds.isEmpty) {
throw Exception(
'Assign at least one IT Staff before completing this task.',
);
}
final itStaffRows = await _client
.from('profiles')
.select('id')
.inFilter('id', assignedUserIds)
.eq('role', 'it_staff');
final hasItStaff = (itStaffRows as List).isNotEmpty;
if (!hasItStaff) {
throw Exception(
'Assign at least one IT Staff before completing this task.',
);
}
// Check required fields
try { try {
final rt = taskRow['request_type']; final rt = taskRow['request_type'];
final rc = taskRow['request_category']; final rc = taskRow['request_category'];

View File

@ -3503,12 +3503,8 @@ class _TaskDetailScreenState extends ConsumerState<TaskDetailScreen>
return chip; return chip;
} }
final statusOptions = _statusOptions.where((status) { // Show all status options - validation happens on selection
if (status == 'in_progress' && !hasAssignedItStaff) { final statusOptions = _statusOptions;
return false;
}
return true;
}).toList();
return PopupMenuButton<String>( return PopupMenuButton<String>(
onSelected: (value) async { onSelected: (value) async {
@ -3606,6 +3602,16 @@ class _TaskDetailScreenState extends ConsumerState<TaskDetailScreen>
return; return;
} }
// Validate IT staff assignment before starting or completing
if ((value == 'in_progress' || value == 'completed') &&
!hasAssignedItStaff) {
showWarningSnackBar(
context,
'Please assign at least one IT Staff member before ${value == 'in_progress' ? 'starting' : 'completing'} this task.',
);
return;
}
// Update DB only Supabase realtime stream will emit the // Update DB only Supabase realtime stream will emit the
// updated task list, so explicit invalidation here causes a // updated task list, so explicit invalidation here causes a
// visible loading/refresh and is unnecessary. // visible loading/refresh and is unnecessary.