Added Type, Category and Signatories on task
This commit is contained in:
@@ -209,21 +209,41 @@ final tasksControllerProvider = Provider<TasksController>((ref) {
|
||||
class TasksController {
|
||||
TasksController(this._client);
|
||||
|
||||
final SupabaseClient _client;
|
||||
// _client is declared dynamic allowing test doubles that mimic only the
|
||||
// subset of methods used by this class. In production it will be a
|
||||
// SupabaseClient instance.
|
||||
final dynamic _client;
|
||||
|
||||
Future<void> createTask({
|
||||
required String title,
|
||||
required String description,
|
||||
String? officeId,
|
||||
String? ticketId,
|
||||
// optional request metadata when creating a task
|
||||
String? requestType,
|
||||
String? requestTypeOther,
|
||||
String? requestCategory,
|
||||
}) async {
|
||||
final actorId = _client.auth.currentUser?.id;
|
||||
final payload = <String, dynamic>{
|
||||
'title': title,
|
||||
'description': description,
|
||||
};
|
||||
if (officeId != null) payload['office_id'] = officeId;
|
||||
if (ticketId != null) payload['ticket_id'] = ticketId;
|
||||
if (officeId != null) {
|
||||
payload['office_id'] = officeId;
|
||||
}
|
||||
if (ticketId != null) {
|
||||
payload['ticket_id'] = ticketId;
|
||||
}
|
||||
if (requestType != null) {
|
||||
payload['request_type'] = requestType;
|
||||
}
|
||||
if (requestTypeOther != null) {
|
||||
payload['request_type_other'] = requestTypeOther;
|
||||
}
|
||||
if (requestCategory != null) {
|
||||
payload['request_category'] = requestCategory;
|
||||
}
|
||||
|
||||
final data = await _client
|
||||
.from('tasks')
|
||||
@@ -291,7 +311,7 @@ class TasksController {
|
||||
.from('profiles')
|
||||
.select('id, role')
|
||||
.inFilter('role', roles);
|
||||
final rows = data as List<dynamic>;
|
||||
final rows = data;
|
||||
final ids = rows
|
||||
.map((row) => row['id'] as String?)
|
||||
.whereType<String>()
|
||||
@@ -303,10 +323,36 @@ class TasksController {
|
||||
}
|
||||
}
|
||||
|
||||
/// Update only the status of a task.
|
||||
///
|
||||
/// Before marking a task as **completed** we enforce that the
|
||||
/// request type/category metadata have been provided. This protects the
|
||||
/// business rule that details must be specified before closing.
|
||||
Future<void> updateTaskStatus({
|
||||
required String taskId,
|
||||
required String status,
|
||||
}) async {
|
||||
if (status == 'completed') {
|
||||
// fetch current metadata to validate
|
||||
try {
|
||||
final row = await _client
|
||||
.from('tasks')
|
||||
.select('request_type, request_category')
|
||||
.eq('id', taskId)
|
||||
.maybeSingle();
|
||||
final rt = row is Map ? row['request_type'] : null;
|
||||
final rc = row is Map ? row['request_category'] : null;
|
||||
if (rt == null || rc == null) {
|
||||
throw Exception(
|
||||
'Request type and category must be set before completing a task.',
|
||||
);
|
||||
}
|
||||
} catch (e) {
|
||||
// rethrow so callers can handle
|
||||
rethrow;
|
||||
}
|
||||
}
|
||||
|
||||
await _client.from('tasks').update({'status': status}).eq('id', taskId);
|
||||
|
||||
// Log important status transitions
|
||||
@@ -330,6 +376,49 @@ class TasksController {
|
||||
}
|
||||
}
|
||||
|
||||
/// Update arbitrary fields on a task row.
|
||||
///
|
||||
/// Primarily used to set request metadata after creation or during
|
||||
/// status transitions.
|
||||
Future<void> updateTask({
|
||||
required String taskId,
|
||||
String? requestType,
|
||||
String? requestTypeOther,
|
||||
String? requestCategory,
|
||||
String? status,
|
||||
String? requestedBy,
|
||||
String? notedBy,
|
||||
String? receivedBy,
|
||||
}) async {
|
||||
final payload = <String, dynamic>{};
|
||||
if (requestType != null) {
|
||||
payload['request_type'] = requestType;
|
||||
}
|
||||
if (requestTypeOther != null) {
|
||||
payload['request_type_other'] = requestTypeOther;
|
||||
}
|
||||
if (requestCategory != null) {
|
||||
payload['request_category'] = requestCategory;
|
||||
}
|
||||
if (requestedBy != null) {
|
||||
payload['requested_by'] = requestedBy;
|
||||
}
|
||||
if (notedBy != null) {
|
||||
payload['noted_by'] = notedBy;
|
||||
}
|
||||
// `performed_by` is derived from task assignments; we don't persist it here.
|
||||
if (receivedBy != null) {
|
||||
payload['received_by'] = receivedBy;
|
||||
}
|
||||
if (status != null) {
|
||||
payload['status'] = status;
|
||||
}
|
||||
if (payload.isEmpty) {
|
||||
return;
|
||||
}
|
||||
await _client.from('tasks').update(payload).eq('id', taskId);
|
||||
}
|
||||
|
||||
// Auto-assignment logic executed once on creation.
|
||||
Future<void> _autoAssignTask({
|
||||
required String taskId,
|
||||
|
||||
Reference in New Issue
Block a user