461 lines
23 KiB
C#
461 lines
23 KiB
C#
using Marco.Pms.DataAccess.Data;
|
|
using Marco.Pms.Model.Activities;
|
|
using Marco.Pms.Model.Dtos.Activities;
|
|
using Marco.Pms.Model.Employees;
|
|
using Marco.Pms.Model.Entitlements;
|
|
using Marco.Pms.Model.Mapper;
|
|
using Marco.Pms.Model.Projects;
|
|
using Marco.Pms.Model.Utilities;
|
|
using Marco.Pms.Model.ViewModels.Activities;
|
|
using Marco.Pms.Model.ViewModels.Employee;
|
|
using Marco.Pms.Services.Service;
|
|
using MarcoBMS.Services.Helpers;
|
|
using Microsoft.AspNetCore.Authorization;
|
|
using Microsoft.AspNetCore.Mvc;
|
|
using Microsoft.CodeAnalysis;
|
|
using Microsoft.EntityFrameworkCore;
|
|
using Document = Marco.Pms.Model.DocumentManager.Document;
|
|
|
|
namespace MarcoBMS.Services.Controllers
|
|
{
|
|
|
|
[Route("api/[controller]")]
|
|
[ApiController]
|
|
[Authorize]
|
|
public class TaskController : ControllerBase
|
|
{
|
|
private readonly ApplicationDbContext _context;
|
|
private readonly UserHelper _userHelper;
|
|
private readonly S3UploadService _s3Service;
|
|
|
|
|
|
public TaskController(ApplicationDbContext context, UserHelper userHelper, S3UploadService s3Service)
|
|
{
|
|
_context = context;
|
|
_userHelper = userHelper;
|
|
_s3Service = s3Service;
|
|
}
|
|
|
|
private Guid GetTenantId()
|
|
{
|
|
return _userHelper.GetTenantId();
|
|
}
|
|
|
|
[HttpPost("assign")]
|
|
public async Task<IActionResult> AssignTask([FromBody] AssignTaskDto assignTask)
|
|
{
|
|
if (!ModelState.IsValid)
|
|
{
|
|
var errors = ModelState.Values
|
|
.SelectMany(v => v.Errors)
|
|
.Select(e => e.ErrorMessage)
|
|
.ToList();
|
|
return BadRequest(ApiResponse<object>.ErrorResponse("Invalid data", errors, 400));
|
|
|
|
}
|
|
var tenantId = GetTenantId();
|
|
var Employee = await _userHelper.GetCurrentEmployeeAsync();
|
|
|
|
var taskAllocation = assignTask.ToTaskAllocationFromAssignTaskDto(Employee.Id, tenantId);
|
|
_context.TaskAllocations.Add(taskAllocation);
|
|
await _context.SaveChangesAsync();
|
|
var response = taskAllocation.ToAssignTaskVMFromTaskAllocation();
|
|
|
|
var teamMembers = new List<TaskMembers> { };
|
|
if (assignTask.TaskTeam != null)
|
|
{
|
|
foreach (var teamMember in assignTask.TaskTeam)
|
|
{
|
|
var result = new TaskMembers
|
|
{
|
|
TaskAllocationId = taskAllocation.Id,
|
|
EmployeeId = teamMember,
|
|
TenantId = tenantId,
|
|
};
|
|
teamMembers.Add(result);
|
|
}
|
|
}
|
|
_context.TaskMembers.AddRange(teamMembers);
|
|
await _context.SaveChangesAsync();
|
|
|
|
var idList = teamMembers.Select(m => m.EmployeeId);
|
|
List<Employee> employees = await _context.Employees.Where(e => idList.Contains(e.Id)).ToListAsync();
|
|
List<BasicEmployeeVM> team = new List<BasicEmployeeVM>();
|
|
foreach (var employee in employees)
|
|
{
|
|
team.Add(employee.ToBasicEmployeeVMFromEmployee());
|
|
}
|
|
response.teamMembers = team;
|
|
return Ok(ApiResponse<object>.SuccessResponse(response, "Task assignned successfully", 200));
|
|
}
|
|
|
|
[HttpPost("report")]
|
|
public async Task<IActionResult> ReportTaskProgress([FromBody] ReportTaskDto reportTask)
|
|
{
|
|
if (!ModelState.IsValid)
|
|
{
|
|
var errors = ModelState.Values
|
|
.SelectMany(v => v.Errors)
|
|
.Select(e => e.ErrorMessage)
|
|
.ToList();
|
|
return BadRequest(ApiResponse<object>.ErrorResponse("Invalid data", errors, 400));
|
|
|
|
}
|
|
var tenantId = GetTenantId();
|
|
var Employee = await _userHelper.GetCurrentEmployeeAsync();
|
|
|
|
var taskAllocation = await _context.TaskAllocations.Include(t => t.WorkItem).FirstOrDefaultAsync(t => t.Id == reportTask.Id);
|
|
|
|
var checkListIds = reportTask.CheckList != null ? reportTask.CheckList.Select(c => c.Id).ToList() : new List<Guid>();
|
|
var checkList = await _context.ActivityCheckLists.Where(c => checkListIds.Contains(c.Id)).ToListAsync();
|
|
if (taskAllocation == null || taskAllocation.WorkItem == null)
|
|
{
|
|
return BadRequest(ApiResponse<object>.ErrorResponse("No such task has been allocated.", "No such task has been allocated.", 400));
|
|
}
|
|
WorkArea workArea = await _context.WorkAreas.Include(a => a.Floor).FirstOrDefaultAsync(a => a.Id == taskAllocation.WorkItem.WorkAreaId) ?? new WorkArea();
|
|
|
|
var bulding = await _context.Buildings.FirstOrDefaultAsync(b => b.Id == (workArea.Floor != null ? workArea.Floor.BuildingId : Guid.Empty));
|
|
if (taskAllocation.WorkItem != null)
|
|
{
|
|
if (taskAllocation.CompletedTask != 0)
|
|
{
|
|
taskAllocation.WorkItem.CompletedWork -= taskAllocation.CompletedTask;
|
|
}
|
|
taskAllocation.ReportedDate = reportTask.ReportedDate;
|
|
taskAllocation.CompletedTask = reportTask.CompletedTask;
|
|
taskAllocation.WorkItem.CompletedWork += reportTask.CompletedTask;
|
|
}
|
|
List<CheckListMappings> checkListMappings = new List<CheckListMappings>();
|
|
List<CheckListVM> checkListVMs = new List<CheckListVM>();
|
|
if (reportTask.CheckList != null)
|
|
{
|
|
foreach (var checkDto in reportTask.CheckList)
|
|
{
|
|
checkListVMs.Add(checkDto.ToCheckListVMFromReportCheckListDto(taskAllocation.WorkItem != null ? taskAllocation.WorkItem.ActivityId : Guid.Empty));
|
|
if (checkDto.IsChecked)
|
|
{
|
|
var check = checkList.Find(c => c.Id == checkDto.Id);
|
|
if (check != null)
|
|
{
|
|
CheckListMappings checkListMapping = new CheckListMappings
|
|
{
|
|
CheckListId = check.Id,
|
|
TaskAllocationId = reportTask.Id
|
|
};
|
|
checkListMappings.Add(checkListMapping);
|
|
}
|
|
}
|
|
}
|
|
}
|
|
_context.CheckListMappings.AddRange(checkListMappings);
|
|
var comment = reportTask.ToCommentFromReportTaskDto(tenantId, Employee.Id);
|
|
|
|
var Images = reportTask.Images;
|
|
|
|
if (Images != null && Images.Count > 0)
|
|
{
|
|
|
|
foreach (var Image in Images)
|
|
{
|
|
|
|
if (string.IsNullOrEmpty(Image.Base64Data))
|
|
return BadRequest(ApiResponse<object>.ErrorResponse("Base64 data is missing", "Base64 data is missing", 400));
|
|
|
|
//If base64 has a data URI prefix, strip it
|
|
var base64 = Image.Base64Data.Contains(",")
|
|
? Image.Base64Data.Substring(Image.Base64Data.IndexOf(",") + 1)
|
|
: Image.Base64Data;
|
|
|
|
string fileType = _s3Service.GetContentTypeFromBase64(base64);
|
|
string fileName = _s3Service.GenerateFileName(fileType, tenantId, "task_report");
|
|
|
|
string objectKey = $"tenant-{tenantId}/project-{bulding?.ProjectId}/Actitvity/{fileName}";
|
|
await _s3Service.UploadFileAsync(base64, fileType, objectKey);
|
|
|
|
Document document = new Document
|
|
{
|
|
FileName = Image.FileName ?? "",
|
|
ContentType = Image.ContentType ?? "",
|
|
S3Key = objectKey,
|
|
Base64Data = Image.Base64Data,
|
|
FileSize = Image.FileSize,
|
|
UploadedAt = DateTime.UtcNow,
|
|
TenantId = tenantId
|
|
};
|
|
_context.Documents.Add(document);
|
|
TaskAttachment attachment = new TaskAttachment
|
|
{
|
|
DocumentId = document.Id,
|
|
ReferenceId = reportTask.Id
|
|
};
|
|
_context.TaskAttachments.Add(attachment);
|
|
}
|
|
await _context.SaveChangesAsync();
|
|
}
|
|
|
|
_context.TaskComments.Add(comment);
|
|
await _context.SaveChangesAsync();
|
|
|
|
var response = taskAllocation.ToReportTaskVMFromTaskAllocation();
|
|
List<TaskComment> comments = await _context.TaskComments.Where(c => c.TaskAllocationId == taskAllocation.Id).ToListAsync();
|
|
List<CommentVM> resultComments = new List<CommentVM> { };
|
|
foreach (var result in comments)
|
|
{
|
|
resultComments.Add(result.ToCommentVMFromTaskComment());
|
|
}
|
|
response.Comments = resultComments;
|
|
response.checkList = checkListVMs;
|
|
return Ok(ApiResponse<object>.SuccessResponse(response, "Task reported successfully", 200));
|
|
}
|
|
|
|
[HttpPost("comment")]
|
|
public async Task<IActionResult> AddCommentForTask([FromBody] CreateCommentDto createComment)
|
|
{
|
|
var tenantId = GetTenantId();
|
|
var Employee = await _userHelper.GetCurrentEmployeeAsync();
|
|
|
|
var taskAllocation = await _context.TaskAllocations.Include(t => t.WorkItem).FirstOrDefaultAsync(t => t.Id == createComment.TaskAllocationId);
|
|
if (taskAllocation == null || taskAllocation.WorkItem == null)
|
|
{
|
|
return BadRequest(ApiResponse<object>.ErrorResponse("No such task has been allocated.", "No such task has been allocated.", 400));
|
|
}
|
|
WorkArea workArea = await _context.WorkAreas.Include(a => a.Floor).FirstOrDefaultAsync(a => a.Id == taskAllocation.WorkItem.WorkAreaId) ?? new WorkArea();
|
|
|
|
var bulding = await _context.Buildings.FirstOrDefaultAsync(b => b.Id == (workArea.Floor != null ? workArea.Floor.BuildingId : Guid.Empty));
|
|
|
|
var comment = createComment.ToCommentFromCommentDto(tenantId, Employee.Id);
|
|
_context.TaskComments.Add(comment);
|
|
await _context.SaveChangesAsync();
|
|
|
|
var Images = createComment.Images;
|
|
|
|
if (Images != null && Images.Count > 0)
|
|
{
|
|
|
|
foreach (var Image in Images)
|
|
{
|
|
|
|
if (string.IsNullOrEmpty(Image.Base64Data))
|
|
return BadRequest(ApiResponse<object>.ErrorResponse("Base64 data is missing", "Base64 data is missing", 400));
|
|
|
|
//If base64 has a data URI prefix, strip it
|
|
var base64 = Image.Base64Data.Contains(",")
|
|
? Image.Base64Data.Substring(Image.Base64Data.IndexOf(",") + 1)
|
|
: Image.Base64Data;
|
|
|
|
string fileType = _s3Service.GetContentTypeFromBase64(base64);
|
|
string fileName = _s3Service.GenerateFileName(fileType, tenantId, "task_report");
|
|
|
|
string objectKey = $"tenant-{tenantId}/project-{bulding?.ProjectId}/Actitvity/{fileName}";
|
|
await _s3Service.UploadFileAsync(base64, fileType, objectKey);
|
|
|
|
Document document = new Document
|
|
{
|
|
FileName = Image.FileName ?? "",
|
|
ContentType = Image.ContentType ?? "",
|
|
S3Key = objectKey,
|
|
Base64Data = Image.Base64Data,
|
|
FileSize = Image.FileSize,
|
|
UploadedAt = DateTime.UtcNow,
|
|
TenantId = tenantId
|
|
};
|
|
_context.Documents.Add(document);
|
|
TaskAttachment attachment = new TaskAttachment
|
|
{
|
|
DocumentId = document.Id,
|
|
ReferenceId = comment.Id
|
|
};
|
|
_context.TaskAttachments.Add(attachment);
|
|
}
|
|
await _context.SaveChangesAsync();
|
|
}
|
|
|
|
CommentVM response = comment.ToCommentVMFromTaskComment();
|
|
return Ok(ApiResponse<object>.SuccessResponse(response, "Comment saved successfully", 200));
|
|
}
|
|
|
|
[HttpGet("list")]
|
|
public async Task<IActionResult> GetTasksList([FromQuery] Guid projectId, [FromQuery] string? dateFrom = null, [FromQuery] string? dateTo = null)
|
|
{
|
|
Guid tenantId = GetTenantId();
|
|
DateTime fromDate = new DateTime();
|
|
DateTime toDate = new DateTime();
|
|
|
|
if (dateFrom != null && DateTime.TryParse(dateFrom, out fromDate) == false)
|
|
{
|
|
return BadRequest(ApiResponse<object>.ErrorResponse("Invalid starting date.", "Invalid starting date.", 400));
|
|
|
|
}
|
|
if (dateTo != null && DateTime.TryParse(dateTo, out toDate) == false)
|
|
{
|
|
return BadRequest(ApiResponse<object>.ErrorResponse("Invalid ending date.", "Invalid ending date.", 400));
|
|
|
|
}
|
|
if (dateFrom == null) fromDate = DateTime.UtcNow.Date;
|
|
if (dateTo == null) toDate = fromDate.AddDays(1);
|
|
|
|
var jobroles = await _context.JobRoles.Where(r => r.TenantId == tenantId).ToListAsync();
|
|
//var taskAllocations = await _context.TaskAllocations.Where(t => t.WorkItem.WorkArea.Floor.Building.ProjectId == projectId && t.AssignmentDate >= fromDate && t.AssignmentDate <= toDate && t.TenantId == tenantId).Include(t => t.WorkItemId).ToListAsync();
|
|
List<Building> buildings = await _context.Buildings.Where(b => b.ProjectId == projectId && b.TenantId == tenantId).ToListAsync();
|
|
List<Guid> idList = buildings.Select(b => b.Id).ToList();
|
|
|
|
List<Floor> floors = await _context.Floor.Where(f => idList.Contains(f.BuildingId) && f.TenantId == tenantId).ToListAsync();
|
|
idList = floors.Select(f => f.Id).ToList();
|
|
|
|
List<WorkArea> workAreas = await _context.WorkAreas.Where(a => idList.Contains(a.FloorId) && a.TenantId == tenantId).ToListAsync();
|
|
idList = workAreas.Select(a => a.Id).ToList();
|
|
|
|
List<WorkItem> workItems = await _context.WorkItems.Where(i => idList.Contains(i.WorkAreaId) && i.TenantId == tenantId).Include(i => i.ActivityMaster).ToListAsync();
|
|
idList = workItems.Select(i => i.Id).ToList();
|
|
var activityIdList = workItems.Select(i => i.ActivityId).ToList();
|
|
|
|
List<TaskAllocation> taskAllocations = await _context.TaskAllocations.Where(t => idList.Contains(t.WorkItemId) && t.AssignmentDate.Date >= fromDate.Date && t.AssignmentDate.Date <= toDate.Date && t.TenantId == tenantId).Include(t => t.WorkItem).Include(t => t.Employee).ToListAsync();
|
|
var taskIdList = taskAllocations.Select(t => t.Id).ToList();
|
|
|
|
List<TaskMembers> teamMembers = await _context.TaskMembers.Where(t => taskIdList.Contains(t.TaskAllocationId)).ToListAsync();
|
|
var employeeIdList = teamMembers.Select(e => e.EmployeeId).ToList();
|
|
|
|
List<Employee> employees = await _context.Employees.Where(e => employeeIdList.Contains(e.Id)).Include(e => e.JobRole).ToListAsync();
|
|
|
|
List<TaskComment> allComments = await _context.TaskComments.Include(c => c.Employee).Where(c => taskIdList.Contains(c.TaskAllocationId)).ToListAsync();
|
|
var allCommentIds = allComments.Select(c => c.Id).ToList();
|
|
|
|
var taskAttachments = await _context.TaskAttachments.Where(t => taskIdList.Contains(t.ReferenceId) || allCommentIds.Contains(t.ReferenceId)).ToListAsync();
|
|
var documentIds = taskAttachments.Select(t => t.DocumentId).ToList();
|
|
var documents = await _context.Documents.Where(d => documentIds.Contains(d.Id)).ToListAsync();
|
|
|
|
List<ListTaskVM> tasks = new List<ListTaskVM>();
|
|
//foreach (var workItem in workItems)
|
|
//{
|
|
foreach (var taskAllocation in taskAllocations)
|
|
{
|
|
|
|
var response = taskAllocation.ToListTaskVMFromTaskAllocation();
|
|
|
|
List<TaskComment> comments = allComments.Where(c => c.TaskAllocationId == taskAllocation.Id).ToList();
|
|
List<BasicEmployeeVM> team = new List<BasicEmployeeVM>();
|
|
List<TaskMembers> taskMembers = teamMembers.Where(m => m.TaskAllocationId == taskAllocation.Id).ToList();
|
|
|
|
var taskDocumentIds = taskAttachments.Where(t => t.ReferenceId == taskAllocation.Id).Select(t => t.DocumentId).ToList();
|
|
var taskDocuments = documents.Where(d => taskDocumentIds.Contains(d.Id)).ToList();
|
|
|
|
List<string> taskPreSignedUrls = new List<string>();
|
|
foreach (var document in taskDocuments)
|
|
{
|
|
string preSignedUrl = _s3Service.GeneratePreSignedUrlAsync(document.S3Key);
|
|
taskPreSignedUrls.Add(preSignedUrl);
|
|
}
|
|
response.ReportedPreSignedUrls = taskPreSignedUrls;
|
|
|
|
foreach (var taskMember in taskMembers)
|
|
{
|
|
var teamMember = employees.Find(e => e.Id == taskMember.EmployeeId);
|
|
if (teamMember != null)
|
|
{
|
|
team.Add(teamMember.ToBasicEmployeeVMFromEmployee());
|
|
}
|
|
}
|
|
List<CommentVM> commentVM = new List<CommentVM> { };
|
|
foreach (var comment in comments)
|
|
{
|
|
var commentDocumentIds = taskAttachments.Where(t => t.ReferenceId == comment.Id).Select(t => t.DocumentId).ToList();
|
|
var commentDocuments = documents.Where(d => commentDocumentIds.Contains(d.Id)).ToList();
|
|
List<string> commentPreSignedUrls = new List<string>();
|
|
foreach (var document in commentDocuments)
|
|
{
|
|
string preSignedUrl = _s3Service.GeneratePreSignedUrlAsync(document.S3Key);
|
|
commentPreSignedUrls.Add(preSignedUrl);
|
|
}
|
|
CommentVM commentVm = comment.ToCommentVMFromTaskComment();
|
|
commentVm.PreSignedUrls = commentPreSignedUrls;
|
|
|
|
commentVM.Add(commentVm);
|
|
}
|
|
List<ActivityCheckList> checkLists = await _context.ActivityCheckLists.Where(x => x.ActivityId == (taskAllocation.WorkItem != null ? taskAllocation.WorkItem.ActivityId : Guid.Empty)).ToListAsync();
|
|
List<CheckListMappings> checkListMappings = await _context.CheckListMappings.Where(c => c.TaskAllocationId == taskAllocation.Id).ToListAsync();
|
|
List<CheckListVM> checkList = new List<CheckListVM>();
|
|
foreach (var check in checkLists)
|
|
{
|
|
var checkListMapping = checkListMappings.Find(c => c.CheckListId == check.Id);
|
|
if (checkListMapping != null)
|
|
{
|
|
checkList.Add(check.ToCheckListVMFromActivityCheckList(check.ActivityId, true));
|
|
}
|
|
else
|
|
{
|
|
checkList.Add(check.ToCheckListVMFromActivityCheckList(check.ActivityId, false));
|
|
}
|
|
}
|
|
response.comments = commentVM;
|
|
response.teamMembers = team;
|
|
response.CheckList = checkList;
|
|
tasks.Add(response);
|
|
}
|
|
|
|
//}
|
|
return Ok(ApiResponse<object>.SuccessResponse(tasks, "Success", 200));
|
|
}
|
|
|
|
[HttpGet("get/{taskId}")]
|
|
public async Task<IActionResult> GetTask(Guid taskId)
|
|
{
|
|
if (taskId == Guid.Empty) return BadRequest(ApiResponse<object>.ErrorResponse("Invalid data", "Invalid data", 400));
|
|
|
|
var taskAllocation = await _context.TaskAllocations.Include(t => t.Tenant).Include(t => t.Employee).Include(t => t.WorkItem).FirstOrDefaultAsync(t => t.Id == taskId);
|
|
if (taskAllocation != null && taskAllocation.Employee != null && taskAllocation.Tenant != null)
|
|
{
|
|
//var employee = await _context.Employees.FirstOrDefaultAsync(e => e.Id == taskAllocation.AssignedBy);
|
|
string employeeName = System.String.Format("{0} {1}", taskAllocation.Employee.FirstName, taskAllocation.Employee.LastName);
|
|
string tenantName = taskAllocation.Tenant.ContactName ?? string.Empty;
|
|
|
|
if (taskAllocation == null) return NotFound(ApiResponse<object>.ErrorResponse("Task Not Found", "Task not found", 404));
|
|
var taskVM = taskAllocation.TaskAllocationToTaskVM(employeeName);
|
|
var comments = await _context.TaskComments.Where(c => c.TaskAllocationId == taskAllocation.Id).ToListAsync();
|
|
var commentIds = comments.Select(c => c.Id).ToList();
|
|
var taskAttachments = await _context.TaskAttachments.Where(t => t.ReferenceId == taskAllocation.Id || commentIds.Contains(t.ReferenceId)).ToListAsync();
|
|
var documentIds = taskAttachments.Select(t => t.DocumentId).ToList();
|
|
var documents = await _context.Documents.Where(d => documentIds.Contains(d.Id)).ToListAsync();
|
|
var team = await _context.TaskMembers.Where(m => m.TaskAllocationId == taskAllocation.Id).Include(m => m.Employee).ToListAsync();
|
|
var teamMembers = new List<EmployeeVM> { };
|
|
|
|
var taskDocumentIds = taskAttachments.Where(t => t.ReferenceId == taskAllocation.Id).Select(t => t.DocumentId).ToList();
|
|
var taskDocuments = documents.Where(d => taskDocumentIds.Contains(d.Id)).ToList();
|
|
|
|
List<string> taskPreSignedUrls = new List<string>();
|
|
foreach (var document in taskDocuments)
|
|
{
|
|
string preSignedUrl = _s3Service.GeneratePreSignedUrlAsync(document.S3Key);
|
|
taskPreSignedUrls.Add(preSignedUrl);
|
|
}
|
|
taskVM.PreSignedUrls = taskPreSignedUrls;
|
|
foreach (var member in team)
|
|
{
|
|
var result = member.Employee != null ? member.Employee.ToEmployeeVMFromEmployee() : new EmployeeVM();
|
|
teamMembers.Add(result);
|
|
}
|
|
List<CommentVM> Comments = new List<CommentVM> { };
|
|
foreach (var comment in comments)
|
|
{
|
|
var commentDocumentIds = taskAttachments.Where(t => t.ReferenceId == comment.Id).Select(t => t.DocumentId).ToList();
|
|
var commentDocuments = documents.Where(d => commentDocumentIds.Contains(d.Id)).ToList();
|
|
List<string> commentPreSignedUrls = new List<string>();
|
|
foreach (var document in commentDocuments)
|
|
{
|
|
string preSignedUrl = _s3Service.GeneratePreSignedUrlAsync(document.S3Key);
|
|
commentPreSignedUrls.Add(preSignedUrl);
|
|
}
|
|
CommentVM commentVM = comment.ToCommentVMFromTaskComment();
|
|
commentVM.PreSignedUrls = commentPreSignedUrls;
|
|
Comments.Add(commentVM);
|
|
}
|
|
taskVM.Comments = Comments;
|
|
taskVM.TeamMembers = teamMembers;
|
|
return Ok(ApiResponse<object>.SuccessResponse(taskVM, "Success", 200));
|
|
}
|
|
|
|
|
|
return NotFound(ApiResponse<object>.ErrorResponse("Task Not Found", "Task not Found", 404));
|
|
}
|
|
}
|
|
}
|