Document_Manager #129
@ -127,17 +127,18 @@ namespace Marco.Pms.Services.Controllers
|
|||||||
#region =================================================================== Contact Notes APIs ===================================================================
|
#region =================================================================== Contact Notes APIs ===================================================================
|
||||||
|
|
||||||
[HttpGet("notes")]
|
[HttpGet("notes")]
|
||||||
public async Task<IActionResult> GetListOFAllNotes([FromQuery] Guid? projectId, [FromQuery] int? pageSize, [FromQuery] int pageNumber)
|
public async Task<IActionResult> GetListOFAllNotes([FromQuery] Guid? projectId, [FromQuery] int pageSize = 20, [FromQuery] int pageNumber = 1)
|
||||||
{
|
{
|
||||||
var response = await _directoryService.GetListOFAllNotes(projectId, pageSize ?? 25, pageNumber);
|
var loggedInEmployee = await _userHelper.GetCurrentEmployeeAsync();
|
||||||
|
var response = await _directoryService.GetListOFAllNotesAsync(projectId, pageSize, pageNumber, tenantId, loggedInEmployee);
|
||||||
return StatusCode(response.StatusCode, response);
|
return StatusCode(response.StatusCode, response);
|
||||||
}
|
}
|
||||||
|
|
||||||
[HttpPost("note")]
|
[HttpPost("note")]
|
||||||
public async Task<IActionResult> CreateContactNote([FromBody] CreateContactNoteDto noteDto)
|
public async Task<IActionResult> CreateContactNote([FromBody] CreateContactNoteDto noteDto)
|
||||||
{
|
{
|
||||||
|
var loggedInEmployee = await _userHelper.GetCurrentEmployeeAsync();
|
||||||
var response = await _directoryService.CreateContactNote(noteDto);
|
var response = await _directoryService.CreateContactNote(noteDto, tenantId, loggedInEmployee); ;
|
||||||
if (response.StatusCode == 200)
|
if (response.StatusCode == 200)
|
||||||
{
|
{
|
||||||
return Ok(response);
|
return Ok(response);
|
||||||
@ -155,7 +156,8 @@ namespace Marco.Pms.Services.Controllers
|
|||||||
[HttpGet("notes/{ContactId}")]
|
[HttpGet("notes/{ContactId}")]
|
||||||
public async Task<IActionResult> GetNoteListByContactId(Guid contactId, [FromQuery] bool active = true)
|
public async Task<IActionResult> GetNoteListByContactId(Guid contactId, [FromQuery] bool active = true)
|
||||||
{
|
{
|
||||||
var response = await _directoryService.GetNoteListByContactId(contactId, active);
|
var loggedInEmployee = await _userHelper.GetCurrentEmployeeAsync();
|
||||||
|
var response = await _directoryService.GetNoteListByContactId(contactId, active, tenantId, loggedInEmployee);
|
||||||
if (response.StatusCode == 200)
|
if (response.StatusCode == 200)
|
||||||
{
|
{
|
||||||
return Ok(response);
|
return Ok(response);
|
||||||
|
@ -560,7 +560,9 @@ namespace Marco.Pms.Services.Service
|
|||||||
.AsNoTracking() // Use AsNoTracking for read-only operations to improve performance.
|
.AsNoTracking() // Use AsNoTracking for read-only operations to improve performance.
|
||||||
.Include(c => c.ContactCategory)
|
.Include(c => c.ContactCategory)
|
||||||
.Include(c => c.CreatedBy)
|
.Include(c => c.CreatedBy)
|
||||||
|
.ThenInclude(e => e!.JobRole)
|
||||||
.Include(c => c.UpdatedBy)
|
.Include(c => c.UpdatedBy)
|
||||||
|
.ThenInclude(e => e!.JobRole)
|
||||||
.FirstOrDefaultAsync(c => c.Id == id && c.IsActive && c.TenantId == tenantId);
|
.FirstOrDefaultAsync(c => c.Id == id && c.IsActive && c.TenantId == tenantId);
|
||||||
if (contact == null)
|
if (contact == null)
|
||||||
{
|
{
|
||||||
@ -611,6 +613,7 @@ namespace Marco.Pms.Services.Service
|
|||||||
.AsNoTracking()
|
.AsNoTracking()
|
||||||
.Include(cb => cb.Bucket)
|
.Include(cb => cb.Bucket)
|
||||||
.ThenInclude(b => b!.CreatedBy)
|
.ThenInclude(b => b!.CreatedBy)
|
||||||
|
.ThenInclude(e => e!.JobRole)
|
||||||
.Where(cb => cb.ContactId == contact.Id && cb.Bucket != null && cb.Bucket.TenantId == tenantId);
|
.Where(cb => cb.ContactId == contact.Id && cb.Bucket != null && cb.Bucket.TenantId == tenantId);
|
||||||
|
|
||||||
if (hasAdminPermission)
|
if (hasAdminPermission)
|
||||||
@ -649,7 +652,9 @@ namespace Marco.Pms.Services.Service
|
|||||||
return await taskDbContext.ContactNotes
|
return await taskDbContext.ContactNotes
|
||||||
.AsNoTracking()
|
.AsNoTracking()
|
||||||
.Include(cn => cn.Createdby)
|
.Include(cn => cn.Createdby)
|
||||||
|
.ThenInclude(e => e!.JobRole)
|
||||||
.Include(cn => cn.UpdatedBy)
|
.Include(cn => cn.UpdatedBy)
|
||||||
|
.ThenInclude(e => e!.JobRole)
|
||||||
.Include(cn => cn.Contact)
|
.Include(cn => cn.Contact)
|
||||||
.Where(cn => cn.ContactId == contact.Id && cn.Createdby != null && cn.Createdby.TenantId == tenantId)
|
.Where(cn => cn.ContactId == contact.Id && cn.Createdby != null && cn.Createdby.TenantId == tenantId)
|
||||||
.Select(cn => _mapper.Map<ContactNoteVM>(cn))
|
.Select(cn => _mapper.Map<ContactNoteVM>(cn))
|
||||||
@ -1240,193 +1245,216 @@ namespace Marco.Pms.Services.Service
|
|||||||
|
|
||||||
#region =================================================================== Contact Notes APIs ===================================================================
|
#region =================================================================== Contact Notes APIs ===================================================================
|
||||||
|
|
||||||
/// <summary>
|
public async Task<ApiResponse<object>> GetListOFAllNotesAsync(Guid? projectId, int pageSize, int pageNumber, Guid tenantId, Employee loggedInEmployee)
|
||||||
/// Retrieves a paginated list of contact notes based on user permissions.
|
|
||||||
/// </summary>
|
|
||||||
/// <param name="pageSize">The number of items per page.</param>
|
|
||||||
/// <param name="pageNumber">The current page number.</param>
|
|
||||||
/// <returns>An ApiResponse containing the paginated notes or an error message.</returns>
|
|
||||||
public async Task<ApiResponse<object>> GetListOFAllNotes(Guid? projectId, int pageSize, int pageNumber)
|
|
||||||
{
|
{
|
||||||
_logger.LogInfo("Attempting to fetch list of all notes. PageSize: {PageSize}, PageNumber: {PageNumber}", pageSize, pageNumber);
|
_logger.LogInfo("Initiating GetListOFAllNotesAsync. TenantId: {TenantId}, ProjectId: {ProjectId}, PageSize: {PageSize}, PageNumber: {PageNumber}, EmployeeId: {EmployeeId}",
|
||||||
|
tenantId, projectId ?? Guid.Empty, pageSize, pageNumber, loggedInEmployee.Id);
|
||||||
|
|
||||||
Guid tenantId = _userHelper.GetTenantId();
|
// Ensure user context is present
|
||||||
var loggedInEmployee = await _userHelper.GetCurrentEmployeeAsync();
|
if (loggedInEmployee.Id == Guid.Empty || tenantId == Guid.Empty)
|
||||||
List<Guid>? projectContactIds = null;
|
|
||||||
|
|
||||||
if (loggedInEmployee == null)
|
|
||||||
{
|
{
|
||||||
_logger.LogWarning("GetListOFAllNotes: LoggedInEmployee is null. Cannot proceed.");
|
_logger.LogWarning("Unauthorized: LoggedInEmployee is null.");
|
||||||
return ApiResponse<object>.ErrorResponse("Unauthorized", "Employee not found.", 403);
|
return ApiResponse<object>.ErrorResponse("Unauthorized", "Employee not found.", 403);
|
||||||
}
|
}
|
||||||
|
|
||||||
// --- Permission Checks ---
|
try
|
||||||
var hasAdminPermission = await _permissionServices.HasPermission(PermissionsMaster.DirectoryAdmin, loggedInEmployee.Id);
|
|
||||||
var hasManagerPermission = await _permissionServices.HasPermission(PermissionsMaster.DirectoryAdmin, loggedInEmployee.Id);
|
|
||||||
var hasUserPermission = await _permissionServices.HasPermission(PermissionsMaster.DirectoryUser, loggedInEmployee.Id);
|
|
||||||
|
|
||||||
IQueryable<ContactNote> notesQuery = _context.ContactNotes
|
|
||||||
.Include(cn => cn.UpdatedBy)
|
|
||||||
.Include(cn => cn.Createdby) // Assuming 'CreatedBy' (PascalCase)
|
|
||||||
.Include(cn => cn.Contact)
|
|
||||||
.Where(cn => cn.TenantId == tenantId)
|
|
||||||
.AsQueryable(); // Start building the query
|
|
||||||
|
|
||||||
if (!hasAdminPermission && !(hasManagerPermission || hasUserPermission))
|
|
||||||
{
|
{
|
||||||
_logger.LogWarning("GetListOFAllNotes: User {EmployeeId} does not have required permissions to access notes for TenantId: {TenantId}", loggedInEmployee.Id, tenantId);
|
// Use a context instance per method call for safety in parallel scenarios
|
||||||
|
await using var context = _dbContextFactory.CreateDbContext();
|
||||||
|
|
||||||
|
// Permission checks (parallel as they're independent)
|
||||||
|
var (hasAdminPermission, hasManagerPermission, hasUserPermission) = await CheckPermissionsAsync(loggedInEmployee.Id);
|
||||||
|
|
||||||
|
// Access control
|
||||||
|
if (!hasAdminPermission && !hasManagerPermission && !hasUserPermission)
|
||||||
|
{
|
||||||
|
_logger.LogWarning("Access Denied. EmployeeId: {EmployeeId}, TenantId: {TenantId}", loggedInEmployee.Id, tenantId);
|
||||||
|
return ApiResponse<object>.ErrorResponse("Access Denied", "You don't have access to view notes.", 403);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Build base query
|
||||||
|
IQueryable<ContactNote> notesQuery = context.ContactNotes
|
||||||
|
.Include(cn => cn.UpdatedBy)
|
||||||
|
.ThenInclude(e => e!.JobRole)
|
||||||
|
.Include(cn => cn.Createdby)
|
||||||
|
.ThenInclude(e => e!.JobRole)
|
||||||
|
.Include(cn => cn.Contact)
|
||||||
|
.Where(cn => cn.TenantId == tenantId);
|
||||||
|
|
||||||
|
// Fetch associated contact IDs for project (if filtering by project)
|
||||||
|
List<Guid>? projectContactIds = null;
|
||||||
|
if (projectId.HasValue)
|
||||||
|
{
|
||||||
|
projectContactIds = await context.ContactProjectMappings
|
||||||
|
.Where(pc => pc.ProjectId == projectId.Value)
|
||||||
|
.Select(pc => pc.ContactId)
|
||||||
|
.ToListAsync();
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!hasAdminPermission) // Manager/User filtering
|
||||||
|
{
|
||||||
|
_logger.LogInfo("Non-admin user. Applying bucket-based filtering. EmployeeId: {EmployeeId}", loggedInEmployee.Id);
|
||||||
|
// Get assigned bucket IDs
|
||||||
|
var assignedBucketIds = await context.EmployeeBucketMappings
|
||||||
|
.Where(eb => eb.EmployeeId == loggedInEmployee.Id)
|
||||||
|
.Select(eb => eb.BucketId)
|
||||||
|
.ToListAsync();
|
||||||
|
|
||||||
|
if (!assignedBucketIds.Any())
|
||||||
|
{
|
||||||
|
_logger.LogInfo("No assigned buckets for user: {EmployeeId}", loggedInEmployee.Id);
|
||||||
|
return ApiResponse<object>.SuccessResponse(new
|
||||||
|
{
|
||||||
|
CurrentPage = pageNumber,
|
||||||
|
TotalPages = 0,
|
||||||
|
Data = new List<ContactNoteVM>()
|
||||||
|
}, "No notes found based on assigned buckets.", 200);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Contacts based on assigned buckets, further filtered by project (if provided)
|
||||||
|
var contactBucketQuery = context.ContactBucketMappings
|
||||||
|
.Where(cb => assignedBucketIds.Contains(cb.BucketId));
|
||||||
|
|
||||||
|
if (projectContactIds != null)
|
||||||
|
{
|
||||||
|
contactBucketQuery = contactBucketQuery.Where(cb => projectContactIds.Contains(cb.ContactId));
|
||||||
|
}
|
||||||
|
|
||||||
|
var contactIds = await contactBucketQuery.Select(cb => cb.ContactId).Distinct().ToListAsync();
|
||||||
|
|
||||||
|
if (!contactIds.Any())
|
||||||
|
{
|
||||||
|
_logger.LogInfo("No contacts found for assigned buckets for user: {EmployeeId}", loggedInEmployee.Id);
|
||||||
|
return ApiResponse<object>.SuccessResponse(new
|
||||||
|
{
|
||||||
|
CurrentPage = pageNumber,
|
||||||
|
TotalPages = 0,
|
||||||
|
Data = new List<ContactNoteVM>()
|
||||||
|
}, "No notes found for associated contacts.", 200);
|
||||||
|
}
|
||||||
|
|
||||||
|
notesQuery = notesQuery.Where(cn => contactIds.Contains(cn.ContactId));
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
// Admin: If project specified, filter notes further
|
||||||
|
if (projectContactIds != null)
|
||||||
|
notesQuery = notesQuery.Where(cn => projectContactIds.Contains(cn.ContactId));
|
||||||
|
}
|
||||||
|
|
||||||
|
// Pagination safeguard
|
||||||
|
pageSize = pageSize < 1 ? 25 : pageSize;
|
||||||
|
pageNumber = pageNumber < 1 ? 1 : pageNumber;
|
||||||
|
|
||||||
|
// Accurate pagination metadata
|
||||||
|
int totalRecords = await notesQuery.CountAsync();
|
||||||
|
int totalPages = (int)Math.Ceiling(totalRecords / (double)pageSize);
|
||||||
|
|
||||||
|
// Fetch paginated, ordered results
|
||||||
|
List<ContactNote> notes = await notesQuery
|
||||||
|
.OrderByDescending(cn => cn.UpdatedAt ?? cn.CreatedAt)
|
||||||
|
.Skip((pageNumber - 1) * pageSize)
|
||||||
|
.Take(pageSize)
|
||||||
|
.ToListAsync();
|
||||||
|
|
||||||
|
_logger.LogInfo("Notes fetched: {Count}, Page: {PageNumber}/{TotalPages}, EmployeeId: {EmployeeId}, TenantId: {TenantId}",
|
||||||
|
notes.Count, pageNumber, totalPages, loggedInEmployee.Id, tenantId);
|
||||||
|
|
||||||
|
// In-memory mapping to ViewModel
|
||||||
|
var noteVms = _mapper.Map<List<ContactNoteVM>>(notes);
|
||||||
|
|
||||||
|
var response = new
|
||||||
|
{
|
||||||
|
CurrentPage = pageNumber,
|
||||||
|
PageSize = pageSize,
|
||||||
|
TotalPages = totalPages,
|
||||||
|
TotalRecords = totalRecords,
|
||||||
|
Data = noteVms
|
||||||
|
};
|
||||||
|
|
||||||
|
_logger.LogInfo("Notes mapped to ViewModel for TenantId: {TenantId}, EmployeeId: {EmployeeId}", tenantId, loggedInEmployee.Id);
|
||||||
|
return ApiResponse<object>.SuccessResponse(response, $"{noteVms.Count} notes fetched successfully.", 200);
|
||||||
|
|
||||||
|
}
|
||||||
|
catch (Exception ex)
|
||||||
|
{
|
||||||
|
_logger.LogError(ex, "Exception occurred in GetListOFAllNotesAsync. TenantId: {TenantId}, EmployeeId: {EmployeeId}", tenantId, loggedInEmployee.Id);
|
||||||
|
return ApiResponse<object>.ErrorResponse("Internal Server Error", "An error occurred while fetching notes. Please try again later.", 500);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
public async Task<ApiResponse<object>> GetNoteListByContactId(Guid id, bool active, Guid tenantId, Employee loggedInEmployee)
|
||||||
|
{
|
||||||
|
var (hasAdminPermission, hasManagerPermission, hasUserPermission) = await CheckPermissionsAsync(loggedInEmployee.Id);
|
||||||
|
|
||||||
|
if (!hasAdminPermission && !hasManagerPermission && !hasUserPermission)
|
||||||
|
{
|
||||||
|
_logger.LogWarning("Access Denied. EmployeeId: {EmployeeId}, TenantId: {TenantId} Do not have permission", loggedInEmployee.Id, tenantId);
|
||||||
return ApiResponse<object>.ErrorResponse("Access Denied", "You don't have access to view notes.", 403);
|
return ApiResponse<object>.ErrorResponse("Access Denied", "You don't have access to view notes.", 403);
|
||||||
}
|
}
|
||||||
if (projectId != null)
|
|
||||||
|
Contact? contact = await _context.Contacts.FirstOrDefaultAsync(c => c.Id == id && c.IsActive && c.TenantId == tenantId);
|
||||||
|
if (contact == null)
|
||||||
{
|
{
|
||||||
projectContactIds = await _context.ContactProjectMappings
|
_logger.LogWarning("Employee with ID {LoggedInEmployeeId} attempted to fetch a list notes from contact with ID {ContactId}, but the contact was not found in the database.", loggedInEmployee.Id, id);
|
||||||
.Where(pc => pc.ProjectId == projectId)
|
return ApiResponse<object>.ErrorResponse("Contact not found", "Contact not found", 404);
|
||||||
.Select(pc => pc.ContactId)
|
|
||||||
.ToListAsync();
|
|
||||||
}
|
}
|
||||||
if (!hasAdminPermission) // If not an admin, apply additional filtering
|
|
||||||
|
if (!hasAdminPermission && (hasManagerPermission || hasUserPermission))
|
||||||
{
|
{
|
||||||
_logger.LogInfo("GetListOFAllNotes: User {EmployeeId} is not an admin. Applying manager/user specific filters.", loggedInEmployee.Id);
|
var bucketIds = await _context.EmployeeBucketMappings.Where(em => em.EmployeeId == loggedInEmployee.Id).Select(em => em.BucketId).ToListAsync();
|
||||||
var assignedBucketIds = await _context.EmployeeBucketMappings
|
var hasContactAccess = await _context.ContactBucketMappings.AnyAsync(cb => bucketIds.Contains(cb.BucketId) && cb.ContactId == contact.Id);
|
||||||
.Where(eb => eb.EmployeeId == loggedInEmployee.Id)
|
if (!hasContactAccess)
|
||||||
.Select(eb => eb.BucketId)
|
|
||||||
.ToListAsync();
|
|
||||||
|
|
||||||
if (!assignedBucketIds.Any())
|
|
||||||
{
|
{
|
||||||
_logger.LogInfo("GetListOFAllNotes: User {EmployeeId} has no assigned buckets. Returning empty list.", loggedInEmployee.Id);
|
_logger.LogWarning("Access Denied. EmployeeId: {EmployeeId}, TenantId: {TenantId} Do not have access of bucket", loggedInEmployee.Id, tenantId);
|
||||||
return ApiResponse<object>.SuccessResponse(new { CurrentPage = pageNumber, TotalPages = 0, Data = new List<ContactNoteVM>() }, "No notes found based on assigned buckets.", 200);
|
return ApiResponse<object>.ErrorResponse("Access Denied", "You don't have access to view notes.", 403);
|
||||||
}
|
|
||||||
|
|
||||||
List<Guid>? contactIds = null;
|
|
||||||
|
|
||||||
if (projectContactIds == null)
|
|
||||||
{
|
|
||||||
contactIds = await _context.ContactBucketMappings
|
|
||||||
.Where(cb => assignedBucketIds.Contains(cb.BucketId))
|
|
||||||
.Select(cb => cb.ContactId)
|
|
||||||
.ToListAsync();
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
contactIds = await _context.ContactBucketMappings
|
|
||||||
.Where(cb => assignedBucketIds.Contains(cb.BucketId) && projectContactIds.Contains(cb.ContactId))
|
|
||||||
.Select(cb => cb.ContactId)
|
|
||||||
.ToListAsync();
|
|
||||||
}
|
|
||||||
|
|
||||||
if (!contactIds.Any())
|
|
||||||
{
|
|
||||||
_logger.LogInfo("GetListOFAllNotes: No contacts found for assigned buckets for user {EmployeeId}. Returning empty list.", loggedInEmployee.Id);
|
|
||||||
return ApiResponse<object>.SuccessResponse(new { CurrentPage = pageNumber, TotalPages = 0, Data = new List<ContactNoteVM>() }, "No notes found for associated contacts.", 200);
|
|
||||||
}
|
|
||||||
|
|
||||||
notesQuery = notesQuery.Where(cn => contactIds.Contains(cn.ContactId));
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
if (projectContactIds != null)
|
|
||||||
{
|
|
||||||
notesQuery = notesQuery.Where(cn => projectContactIds.Contains(cn.ContactId));
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// --- Pagination Logic ---
|
var notesQuery = _context.ContactNotes
|
||||||
// Ensure pageSize and pageNumber are valid
|
.Include(n => n.Createdby)
|
||||||
pageSize = pageSize < 1 ? 25 : pageSize; // Default to 25 if less than 1
|
.ThenInclude(e => e!.JobRole)
|
||||||
pageNumber = pageNumber < 1 ? 1 : pageNumber; // Default to 1 if less than 1
|
.Include(n => n.UpdatedBy)
|
||||||
|
.ThenInclude(e => e!.JobRole)
|
||||||
|
.Where(n => n.ContactId == contact.Id && n.TenantId == tenantId);
|
||||||
|
|
||||||
// Get total count BEFORE applying Skip/Take for accurate pagination metadata
|
if (active)
|
||||||
int totalRecords = await notesQuery.CountAsync();
|
{
|
||||||
int totalPages = (int)Math.Ceiling((double)totalRecords / pageSize);
|
notesQuery = notesQuery.Where(n => n.IsActive);
|
||||||
|
}
|
||||||
|
|
||||||
int skip = (pageNumber - 1) * pageSize;
|
List<ContactNote> notes = await notesQuery.ToListAsync();
|
||||||
|
|
||||||
// --- Apply Ordering and Pagination in the database ---
|
var noteIds = notes.Select(n => n.Id).ToList();
|
||||||
List<ContactNote> notes = await notesQuery
|
List<DirectoryUpdateLog>? updateLogs = await _context.DirectoryUpdateLogs
|
||||||
.OrderByDescending(cn => (cn.UpdatedAt != null ? cn.UpdatedAt : cn.CreatedAt)) // Order by updated date or created date
|
.Include(l => l.Employee)
|
||||||
.Skip((pageNumber - 1) * pageSize)
|
.ThenInclude(e => e!.JobRole)
|
||||||
.Take(pageSize)
|
.Where(l => noteIds.Contains(l.RefereanceId))
|
||||||
.ToListAsync();
|
.ToListAsync();
|
||||||
|
|
||||||
_logger.LogInfo("GetListOFAllNotes: Fetched {Count} notes for page {PageNumber} of {TotalPages} total pages. Total records: {TotalRecords}.",
|
List<ContactNoteVM> noteVMs = _mapper.Map<List<ContactNoteVM>>(notes);
|
||||||
notes.Count, pageNumber, totalPages, totalRecords);
|
|
||||||
|
|
||||||
// --- Map to ViewModel (in-memory) ---
|
_logger.LogInfo("{count} contact-notes record from contact {ContactId} fetched by Employee {EmployeeId}", noteVMs.Count, id, loggedInEmployee.Id);
|
||||||
// This mapping is done in memory because ToBasicEmployeeVMFromEmployee() is likely a C# method
|
return ApiResponse<object>.SuccessResponse(noteVMs, $"{noteVMs.Count} contact-notes record fetched successfully", 200);
|
||||||
// that cannot be translated to SQL by Entity Framework.
|
|
||||||
|
|
||||||
List<ContactNoteVM> noteVMS = notes
|
|
||||||
.Select(cn => cn.ToContactNoteVMFromContactNote())
|
|
||||||
.ToList();
|
|
||||||
|
|
||||||
var response = new
|
|
||||||
{
|
|
||||||
CurrentPage = pageNumber,
|
|
||||||
PageSize = pageSize, // Include pageSize in response for client clarity
|
|
||||||
TotalPages = totalPages,
|
|
||||||
TotalRecords = totalRecords, // Add total records for client
|
|
||||||
Data = noteVMS
|
|
||||||
};
|
|
||||||
|
|
||||||
_logger.LogInfo("GetListOFAllNotes: Successfully retrieved notes and mapped to ViewModel for TenantId: {TenantId}.", tenantId);
|
|
||||||
return ApiResponse<object>.SuccessResponse(response, $"{noteVMS.Count} notes fetched successfully.", 200);
|
|
||||||
}
|
}
|
||||||
public async Task<ApiResponse<object>> GetNoteListByContactId(Guid id, bool active)
|
|
||||||
{
|
|
||||||
Guid tenantId = _userHelper.GetTenantId();
|
|
||||||
var LoggedInEmployee = await _userHelper.GetCurrentEmployeeAsync();
|
|
||||||
Contact? contact = await _context.Contacts.FirstOrDefaultAsync(c => c.Id == id && c.IsActive && c.TenantId == tenantId);
|
|
||||||
if (contact != null)
|
|
||||||
{
|
|
||||||
List<ContactNote> notes = new List<ContactNote>();
|
|
||||||
if (active)
|
|
||||||
{
|
|
||||||
notes = await _context.ContactNotes
|
|
||||||
.Include(n => n.Createdby)
|
|
||||||
.Include(n => n.UpdatedBy)
|
|
||||||
.Where(n => n.ContactId == contact.Id && n.IsActive && n.TenantId == tenantId)
|
|
||||||
.ToListAsync();
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
notes = await _context.ContactNotes
|
|
||||||
.Include(n => n.Createdby)
|
|
||||||
.Include(n => n.UpdatedBy)
|
|
||||||
.Where(n => n.ContactId == contact.Id && n.TenantId == tenantId)
|
|
||||||
.ToListAsync();
|
|
||||||
}
|
|
||||||
var noteIds = notes.Select(n => n.Id).ToList();
|
|
||||||
List<DirectoryUpdateLog>? updateLogs = await _context.DirectoryUpdateLogs.Include(l => l.Employee).Where(l => noteIds.Contains(l.RefereanceId)).ToListAsync();
|
|
||||||
//List<ContactNoteVM>? noteVMs = new List<ContactNoteVM>();
|
|
||||||
List<ContactNoteVM>? noteVMs = notes.Select(n => n.ToContactNoteVMFromContactNote()).ToList();
|
|
||||||
|
|
||||||
_logger.LogInfo("{count} contact-notes record from contact {ContactId} fetched by Employee {EmployeeId}", noteVMs.Count, id, LoggedInEmployee.Id);
|
public async Task<ApiResponse<object>> CreateContactNote(CreateContactNoteDto noteDto, Guid tenantId, Employee loggedInEmployee)
|
||||||
return ApiResponse<object>.SuccessResponse(noteVMs, $"{noteVMs.Count} contact-notes record fetched successfully", 200);
|
|
||||||
}
|
|
||||||
_logger.LogWarning("Employee with ID {LoggedInEmployeeId} attempted to fetch a list notes from contact with ID {ContactId}, but the contact was not found in the database.", LoggedInEmployee.Id, id);
|
|
||||||
return ApiResponse<object>.ErrorResponse("Contact not found", "Contact not found", 404);
|
|
||||||
}
|
|
||||||
public async Task<ApiResponse<object>> CreateContactNote(CreateContactNoteDto noteDto)
|
|
||||||
{
|
{
|
||||||
Guid tenantId = _userHelper.GetTenantId();
|
|
||||||
var LoggedInEmployee = await _userHelper.GetCurrentEmployeeAsync();
|
|
||||||
if (noteDto != null)
|
if (noteDto != null)
|
||||||
{
|
{
|
||||||
Contact? contact = await _context.Contacts.FirstOrDefaultAsync(c => c.Id == noteDto.ContactId && c.IsActive && c.TenantId == tenantId);
|
Contact? contact = await _context.Contacts.FirstOrDefaultAsync(c => c.Id == noteDto.ContactId && c.IsActive && c.TenantId == tenantId);
|
||||||
if (contact != null)
|
if (contact != null)
|
||||||
{
|
{
|
||||||
ContactNote note = noteDto.ToContactNoteFromCreateContactNoteDto(tenantId, LoggedInEmployee.Id);
|
ContactNote note = noteDto.ToContactNoteFromCreateContactNoteDto(tenantId, loggedInEmployee.Id);
|
||||||
_context.ContactNotes.Add(note);
|
_context.ContactNotes.Add(note);
|
||||||
await _context.SaveChangesAsync();
|
await _context.SaveChangesAsync();
|
||||||
ContactNoteVM noteVM = note.ToContactNoteVMFromContactNote();
|
ContactNoteVM noteVM = note.ToContactNoteVMFromContactNote();
|
||||||
_logger.LogInfo("Employee {EmployeeId} Added note at contact {ContactId}", LoggedInEmployee.Id, contact.Id);
|
_logger.LogInfo("Employee {EmployeeId} Added note at contact {ContactId}", loggedInEmployee.Id, contact.Id);
|
||||||
return ApiResponse<object>.SuccessResponse(noteVM, "Note added successfully", 200);
|
return ApiResponse<object>.SuccessResponse(noteVM, "Note added successfully", 200);
|
||||||
}
|
}
|
||||||
_logger.LogWarning("Employee with ID {LoggedInEmployeeId} attempted to add a note to contact with ID {ContactId}, but the contact was not found in the database.", LoggedInEmployee.Id, noteDto.ContactId);
|
_logger.LogWarning("Employee with ID {LoggedInEmployeeId} attempted to add a note to contact with ID {ContactId}, but the contact was not found in the database.", loggedInEmployee.Id, noteDto.ContactId);
|
||||||
return ApiResponse<object>.ErrorResponse("Contact not found", "Contact not found", 404);
|
return ApiResponse<object>.ErrorResponse("Contact not found", "Contact not found", 404);
|
||||||
}
|
}
|
||||||
_logger.LogWarning("Employee with ID {LoggedInEmployeeId} sended empty payload", LoggedInEmployee.Id);
|
_logger.LogWarning("Employee with ID {LoggedInEmployeeId} sended empty payload", loggedInEmployee.Id);
|
||||||
return ApiResponse<object>.ErrorResponse("User Send empty Payload", "User Send empty Payload", 400);
|
return ApiResponse<object>.ErrorResponse("User Send empty Payload", "User Send empty Payload", 400);
|
||||||
}
|
}
|
||||||
public async Task<ApiResponse<object>> UpdateContactNote(Guid id, UpdateContactNoteDto noteDto)
|
public async Task<ApiResponse<object>> UpdateContactNote(Guid id, UpdateContactNoteDto noteDto)
|
||||||
@ -1438,7 +1466,11 @@ namespace Marco.Pms.Services.Service
|
|||||||
Contact? contact = await _context.Contacts.FirstOrDefaultAsync(c => c.Id == noteDto.ContactId && c.TenantId == tenantId);
|
Contact? contact = await _context.Contacts.FirstOrDefaultAsync(c => c.Id == noteDto.ContactId && c.TenantId == tenantId);
|
||||||
if (contact != null)
|
if (contact != null)
|
||||||
{
|
{
|
||||||
ContactNote? contactNote = await _context.ContactNotes.Include(cn => cn.Createdby).Include(cn => cn.Contact).FirstOrDefaultAsync(n => n.Id == noteDto.Id && n.ContactId == contact.Id && n.IsActive);
|
ContactNote? contactNote = await _context.ContactNotes
|
||||||
|
.Include(cn => cn.Createdby)
|
||||||
|
.ThenInclude(e => e!.JobRole)
|
||||||
|
.Include(cn => cn.Contact)
|
||||||
|
.FirstOrDefaultAsync(n => n.Id == noteDto.Id && n.ContactId == contact.Id && n.IsActive);
|
||||||
if (contactNote != null)
|
if (contactNote != null)
|
||||||
{
|
{
|
||||||
contactNote.Note = noteDto.Note;
|
contactNote.Note = noteDto.Note;
|
||||||
@ -1519,6 +1551,7 @@ namespace Marco.Pms.Services.Service
|
|||||||
// Admin gets all buckets for the tenant
|
// Admin gets all buckets for the tenant
|
||||||
bucketList = await _context.Buckets
|
bucketList = await _context.Buckets
|
||||||
.Include(b => b.CreatedBy)
|
.Include(b => b.CreatedBy)
|
||||||
|
.ThenInclude(e => e!.JobRole)
|
||||||
.Where(b => b.TenantId == tenantId)
|
.Where(b => b.TenantId == tenantId)
|
||||||
.ToListAsync();
|
.ToListAsync();
|
||||||
|
|
||||||
@ -1536,6 +1569,7 @@ namespace Marco.Pms.Services.Service
|
|||||||
|
|
||||||
bucketList = await _context.Buckets
|
bucketList = await _context.Buckets
|
||||||
.Include(b => b.CreatedBy)
|
.Include(b => b.CreatedBy)
|
||||||
|
.ThenInclude(e => e!.JobRole)
|
||||||
.Where(b => bucketIds.Contains(b.Id) || b.CreatedByID == loggedInEmployee.Id)
|
.Where(b => bucketIds.Contains(b.Id) || b.CreatedByID == loggedInEmployee.Id)
|
||||||
.ToListAsync();
|
.ToListAsync();
|
||||||
|
|
||||||
@ -1779,7 +1813,6 @@ namespace Marco.Pms.Services.Service
|
|||||||
return ApiResponse<object>.ErrorResponse("An unexpected error occurred. Please try again later.", "Internal server error", 500);
|
return ApiResponse<object>.ErrorResponse("An unexpected error occurred. Please try again later.", "Internal server error", 500);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public async Task<ApiResponse<object>> AssignBucketAsync(Guid bucketId, List<AssignBucketDto> assignBuckets, Guid tenantId, Employee loggedInEmployee)
|
public async Task<ApiResponse<object>> AssignBucketAsync(Guid bucketId, List<AssignBucketDto> assignBuckets, Guid tenantId, Employee loggedInEmployee)
|
||||||
{
|
{
|
||||||
// Validate input payload
|
// Validate input payload
|
||||||
@ -1794,8 +1827,10 @@ namespace Marco.Pms.Services.Service
|
|||||||
|
|
||||||
|
|
||||||
// Load the bucket with related CreatedBy and validate tenant
|
// Load the bucket with related CreatedBy and validate tenant
|
||||||
var bucket = await _context.Buckets.Include(b => b.CreatedBy)
|
var bucket = await _context.Buckets
|
||||||
.FirstOrDefaultAsync(b => b.Id == bucketId && b.TenantId == tenantId);
|
.Include(b => b.CreatedBy)
|
||||||
|
.ThenInclude(e => e!.JobRole)
|
||||||
|
.FirstOrDefaultAsync(b => b.Id == bucketId && b.TenantId == tenantId);
|
||||||
|
|
||||||
if (bucket == null)
|
if (bucket == null)
|
||||||
{
|
{
|
||||||
@ -1931,7 +1966,6 @@ namespace Marco.Pms.Services.Service
|
|||||||
|
|
||||||
return ApiResponse<object>.SuccessResponse(bucketVm, "Bucket details updated successfully", 200);
|
return ApiResponse<object>.SuccessResponse(bucketVm, "Bucket details updated successfully", 200);
|
||||||
}
|
}
|
||||||
|
|
||||||
public async Task<ApiResponse<object>> DeleteBucketAsync(Guid id, Guid tenantId, Employee loggedInEmployee)
|
public async Task<ApiResponse<object>> DeleteBucketAsync(Guid id, Guid tenantId, Employee loggedInEmployee)
|
||||||
{
|
{
|
||||||
try
|
try
|
||||||
|
@ -16,9 +16,12 @@ namespace Marco.Pms.Services.Service.ServiceInterfaces
|
|||||||
Task<ApiResponse<object>> DeleteContactAsync(Guid id, bool active, Guid tenantId, Employee loggedInEmployee);
|
Task<ApiResponse<object>> DeleteContactAsync(Guid id, bool active, Guid tenantId, Employee loggedInEmployee);
|
||||||
|
|
||||||
|
|
||||||
Task<ApiResponse<object>> GetListOFAllNotes(Guid? projectId, int pageSize, int pageNumber);
|
|
||||||
Task<ApiResponse<object>> GetNoteListByContactId(Guid id, bool active);
|
|
||||||
Task<ApiResponse<object>> CreateContactNote(CreateContactNoteDto noteDto);
|
|
||||||
|
Task<ApiResponse<object>> GetListOFAllNotesAsync(Guid? projectId, int pageSize, int pageNumber, Guid tenantId, Employee loggedInEmployee);
|
||||||
|
Task<ApiResponse<object>> GetNoteListByContactId(Guid id, bool active, Guid tenantId, Employee loggedInEmployee);
|
||||||
|
Task<ApiResponse<object>> CreateContactNote(CreateContactNoteDto noteDto, Guid tenantId, Employee loggedInEmployee);
|
||||||
Task<ApiResponse<object>> UpdateContactNote(Guid id, UpdateContactNoteDto noteDto);
|
Task<ApiResponse<object>> UpdateContactNote(Guid id, UpdateContactNoteDto noteDto);
|
||||||
Task<ApiResponse<object>> DeleteContactNote(Guid id, bool active);
|
Task<ApiResponse<object>> DeleteContactNote(Guid id, bool active);
|
||||||
|
|
||||||
|
Loading…
x
Reference in New Issue
Block a user