Activity logs
This commit is contained in:
@@ -210,8 +210,10 @@ final tasksProvider = StreamProvider<List<Task>>((ref) {
|
||||
return 1;
|
||||
case 'completed':
|
||||
return 2;
|
||||
default:
|
||||
case 'cancelled':
|
||||
return 3;
|
||||
default:
|
||||
return 4;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -700,7 +702,13 @@ class TasksController {
|
||||
Future<void> updateTaskStatus({
|
||||
required String taskId,
|
||||
required String status,
|
||||
String? reason,
|
||||
}) async {
|
||||
if (status == 'cancelled') {
|
||||
if (reason == null || reason.trim().isEmpty) {
|
||||
throw Exception('Cancellation requires a reason.');
|
||||
}
|
||||
}
|
||||
if (status == 'completed') {
|
||||
// fetch current metadata to validate several required fields
|
||||
try {
|
||||
@@ -751,7 +759,23 @@ class TasksController {
|
||||
}
|
||||
}
|
||||
|
||||
await _client.from('tasks').update({'status': status}).eq('id', taskId);
|
||||
// persist status and cancellation reason (when provided)
|
||||
final payload = <String, dynamic>{'status': status};
|
||||
if (status == 'cancelled') {
|
||||
payload['cancellation_reason'] = reason;
|
||||
}
|
||||
await _client.from('tasks').update(payload).eq('id', taskId);
|
||||
|
||||
// if cancelled, also set cancelled_at timestamp
|
||||
if (status == 'cancelled') {
|
||||
try {
|
||||
final cancelledAt = AppTime.now().toIso8601String();
|
||||
await _client
|
||||
.from('tasks')
|
||||
.update({'cancelled_at': cancelledAt})
|
||||
.eq('id', taskId);
|
||||
} catch (_) {}
|
||||
}
|
||||
|
||||
// Log important status transitions
|
||||
try {
|
||||
@@ -768,6 +792,13 @@ class TasksController {
|
||||
'actor_id': actorId,
|
||||
'action_type': 'completed',
|
||||
});
|
||||
} else if (status == 'cancelled') {
|
||||
await _insertActivityRows(_client, {
|
||||
'task_id': taskId,
|
||||
'actor_id': actorId,
|
||||
'action_type': 'cancelled',
|
||||
'meta': {'reason': reason},
|
||||
});
|
||||
}
|
||||
} catch (_) {
|
||||
// ignore logging failures
|
||||
@@ -823,7 +854,66 @@ class TasksController {
|
||||
if (payload.isEmpty) {
|
||||
return;
|
||||
}
|
||||
|
||||
await _client.from('tasks').update(payload).eq('id', taskId);
|
||||
|
||||
// Record activity logs for any metadata/signatory fields that were changed
|
||||
try {
|
||||
final actorId = _client.auth.currentUser?.id;
|
||||
final List<Map<String, dynamic>> logRows = [];
|
||||
if (requestType != null) {
|
||||
logRows.add({
|
||||
'task_id': taskId,
|
||||
'actor_id': actorId,
|
||||
'action_type': 'filled_request_type',
|
||||
'meta': {'value': requestType},
|
||||
});
|
||||
}
|
||||
if (requestCategory != null) {
|
||||
logRows.add({
|
||||
'task_id': taskId,
|
||||
'actor_id': actorId,
|
||||
'action_type': 'filled_request_category',
|
||||
'meta': {'value': requestCategory},
|
||||
});
|
||||
}
|
||||
if (requestedBy != null) {
|
||||
logRows.add({
|
||||
'task_id': taskId,
|
||||
'actor_id': actorId,
|
||||
'action_type': 'filled_requested_by',
|
||||
'meta': {'value': requestedBy},
|
||||
});
|
||||
}
|
||||
if (notedBy != null) {
|
||||
logRows.add({
|
||||
'task_id': taskId,
|
||||
'actor_id': actorId,
|
||||
'action_type': 'filled_noted_by',
|
||||
'meta': {'value': notedBy},
|
||||
});
|
||||
}
|
||||
if (receivedBy != null) {
|
||||
logRows.add({
|
||||
'task_id': taskId,
|
||||
'actor_id': actorId,
|
||||
'action_type': 'filled_received_by',
|
||||
'meta': {'value': receivedBy},
|
||||
});
|
||||
}
|
||||
if (actionTaken != null) {
|
||||
logRows.add({
|
||||
'task_id': taskId,
|
||||
'actor_id': actorId,
|
||||
'action_type': 'filled_action_taken',
|
||||
'meta': {'value': actionTaken},
|
||||
});
|
||||
}
|
||||
|
||||
if (logRows.isNotEmpty) {
|
||||
await _insertActivityRows(_client, logRows);
|
||||
}
|
||||
} catch (_) {}
|
||||
}
|
||||
|
||||
/// Update editable task fields such as title, description, office or linked ticket.
|
||||
@@ -1230,10 +1320,11 @@ class TaskAssignmentsController {
|
||||
if (p != null) {
|
||||
if (p['full_name'] != null) {
|
||||
actorName = p['full_name'].toString();
|
||||
} else if (p['display_name'] != null)
|
||||
} else if (p['display_name'] != null) {
|
||||
actorName = p['display_name'].toString();
|
||||
else if (p['name'] != null)
|
||||
} else if (p['name'] != null) {
|
||||
actorName = p['name'].toString();
|
||||
}
|
||||
}
|
||||
} catch (_) {}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user