Document_Manager #129

Merged
ashutosh.nehete merged 83 commits from Document_Manager into main 2025-09-11 04:12:01 +00:00
4 changed files with 79 additions and 9 deletions
Showing only changes of commit 672046d02e - Show all commits

View File

@ -0,0 +1,8 @@
namespace Marco.Pms.Model.Utilities
{
public class ContactNoteFilter
{
public List<Guid>? CreatedByIds { get; set; }
public List<string>? Organizations { get; set; }
}
}

View File

@ -142,10 +142,10 @@ 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 = 20, [FromQuery] int pageNumber = 1) public async Task<IActionResult> GetListOFAllNotes([FromQuery] Guid? projectId, [FromQuery] string? searchString, [FromQuery] string? filter, [FromQuery] int pageSize = 20, [FromQuery] int pageNumber = 1)
{ {
var loggedInEmployee = await _userHelper.GetCurrentEmployeeAsync(); var loggedInEmployee = await _userHelper.GetCurrentEmployeeAsync();
var response = await _directoryService.GetListOFAllNotesAsync(projectId, pageSize, pageNumber, tenantId, loggedInEmployee); var response = await _directoryService.GetListOFAllNotesAsync(projectId, searchString, filter, pageSize, pageNumber, tenantId, loggedInEmployee);
return StatusCode(response.StatusCode, response); return StatusCode(response.StatusCode, response);
} }

View File

@ -118,7 +118,7 @@ namespace Marco.Pms.Services.Service
} }
// --- Advanced Filtering from 'filter' parameter --- // --- Advanced Filtering from 'filter' parameter ---
ContactFilterDto? contactFilter = TryDeserializeFilter(filter); ContactFilterDto? contactFilter = TryDeserializeContactFilter(filter);
if (contactFilter?.BucketIds?.Any() ?? false) if (contactFilter?.BucketIds?.Any() ?? false)
{ {
// Note: Permission filtering is already applied. Here we further restrict by the user's filter choice. // Note: Permission filtering is already applied. Here we further restrict by the user's filter choice.
@ -918,7 +918,6 @@ namespace Marco.Pms.Services.Service
} }
} }
#endregion #endregion
#region =================================================================== Contact Post APIs =================================================================== #region =================================================================== Contact Post APIs ===================================================================
@ -1513,7 +1512,7 @@ namespace Marco.Pms.Services.Service
#region =================================================================== Contact Notes APIs =================================================================== #region =================================================================== Contact Notes APIs ===================================================================
public async Task<ApiResponse<object>> GetListOFAllNotesAsync(Guid? projectId, int pageSize, int pageNumber, Guid tenantId, Employee loggedInEmployee) public async Task<ApiResponse<object>> GetListOFAllNotesAsync(Guid? projectId, string? searchString, string? filter, int pageSize, int pageNumber, Guid tenantId, Employee loggedInEmployee)
{ {
_logger.LogInfo("Initiating GetListOFAllNotesAsync. TenantId: {TenantId}, ProjectId: {ProjectId}, PageSize: {PageSize}, PageNumber: {PageNumber}, EmployeeId: {EmployeeId}", _logger.LogInfo("Initiating GetListOFAllNotesAsync. TenantId: {TenantId}, ProjectId: {ProjectId}, PageSize: {PageSize}, PageNumber: {PageNumber}, EmployeeId: {EmployeeId}",
tenantId, projectId ?? Guid.Empty, pageSize, pageNumber, loggedInEmployee.Id); tenantId, projectId ?? Guid.Empty, pageSize, pageNumber, loggedInEmployee.Id);
@ -1610,6 +1609,31 @@ namespace Marco.Pms.Services.Service
notesQuery = notesQuery.Where(cn => projectContactIds.Contains(cn.ContactId)); notesQuery = notesQuery.Where(cn => projectContactIds.Contains(cn.ContactId));
} }
// --- Advanced Filtering from 'filter' parameter ---
ContactNoteFilter? contactNoteFilter = TryDeserializeContactNoteFilter(filter);
if (contactNoteFilter != null)
{
if (contactNoteFilter.CreatedByIds?.Any() ?? false)
{
notesQuery = notesQuery.Where(cn => contactNoteFilter.CreatedByIds.Contains(cn.CreatedById));
}
if (contactNoteFilter.Organizations?.Any() ?? false)
{
notesQuery = notesQuery.Where(cn => cn.Contact != null && contactNoteFilter.Organizations.Contains(cn.Contact.Organization));
}
}
// --- Search Term Filtering ---
if (!string.IsNullOrWhiteSpace(searchString))
{
var searchTermLower = searchString.ToLower();
notesQuery = notesQuery.Where(c =>
(c.Contact != null && c.Contact.Name.ToLower().Contains(searchTermLower)) ||
(c.Contact != null && c.Contact.Organization != null && c.Contact.Organization.ToLower().Contains(searchTermLower)) ||
c.Note.ToLower().Contains(searchTermLower)
);
}
// Pagination safeguard // Pagination safeguard
pageSize = pageSize < 1 ? 25 : pageSize; pageSize = pageSize < 1 ? 25 : pageSize;
pageNumber = pageNumber < 1 ? 1 : pageNumber; pageNumber = pageNumber < 1 ? 1 : pageNumber;
@ -2735,7 +2759,7 @@ namespace Marco.Pms.Services.Service
return result; return result;
} }
private ContactFilterDto? TryDeserializeFilter(string? filter) private ContactFilterDto? TryDeserializeContactFilter(string? filter)
{ {
if (string.IsNullOrWhiteSpace(filter)) if (string.IsNullOrWhiteSpace(filter))
{ {
@ -2752,7 +2776,7 @@ namespace Marco.Pms.Services.Service
} }
catch (JsonException ex) catch (JsonException ex)
{ {
_logger.LogError(ex, "[{MethodName}] Failed to directly deserialize filter. Attempting to unescape and re-parse. Filter: {Filter}", nameof(TryDeserializeFilter), filter); _logger.LogError(ex, "[{MethodName}] Failed to directly deserialize filter. Attempting to unescape and re-parse. Filter: {Filter}", nameof(TryDeserializeContactFilter), filter);
// If direct deserialization fails, it might be an escaped string (common with tools like Postman or some mobile clients). // If direct deserialization fails, it might be an escaped string (common with tools like Postman or some mobile clients).
try try
@ -2767,7 +2791,45 @@ namespace Marco.Pms.Services.Service
catch (JsonException ex1) catch (JsonException ex1)
{ {
// If both attempts fail, log the final error and return null. // If both attempts fail, log the final error and return null.
_logger.LogError(ex1, "[{MethodName}] All attempts to deserialize the filter failed. Filter will be ignored. Filter: {Filter}", nameof(TryDeserializeFilter), filter); _logger.LogError(ex1, "[{MethodName}] All attempts to deserialize the filter failed. Filter will be ignored. Filter: {Filter}", nameof(TryDeserializeContactFilter), filter);
return null;
}
}
return expenseFilter;
}
private ContactNoteFilter? TryDeserializeContactNoteFilter(string? filter)
{
if (string.IsNullOrWhiteSpace(filter))
{
return null;
}
var options = new JsonSerializerOptions { PropertyNameCaseInsensitive = true };
ContactNoteFilter? expenseFilter = null;
try
{
// First, try to deserialize directly. This is the expected case (e.g., from a web client).
expenseFilter = JsonSerializer.Deserialize<ContactNoteFilter>(filter, options);
}
catch (JsonException ex)
{
_logger.LogError(ex, "[{MethodName}] Failed to directly deserialize filter. Attempting to unescape and re-parse. Filter: {Filter}", nameof(TryDeserializeContactNoteFilter), filter);
// If direct deserialization fails, it might be an escaped string (common with tools like Postman or some mobile clients).
try
{
// Unescape the string first, then deserialize the result.
string unescapedJsonString = JsonSerializer.Deserialize<string>(filter, options) ?? "";
if (!string.IsNullOrWhiteSpace(unescapedJsonString))
{
expenseFilter = JsonSerializer.Deserialize<ContactNoteFilter>(unescapedJsonString, options);
}
}
catch (JsonException ex1)
{
// If both attempts fail, log the final error and return null.
_logger.LogError(ex1, "[{MethodName}] All attempts to deserialize the filter failed. Filter will be ignored. Filter: {Filter}", nameof(TryDeserializeContactNoteFilter), filter);
return null; return null;
} }
} }

View File

@ -21,7 +21,7 @@ namespace Marco.Pms.Services.Service.ServiceInterfaces
Task<ApiResponse<object>> GetListOFAllNotesAsync(Guid? projectId, int pageSize, int pageNumber, Guid tenantId, Employee loggedInEmployee); Task<ApiResponse<object>> GetListOFAllNotesAsync(Guid? projectId, string? searchString, string? filter, int pageSize, int pageNumber, Guid tenantId, Employee loggedInEmployee);
Task<ApiResponse<object>> GetNoteListByContactIdAsync(Guid id, bool active, Guid tenantId, Employee loggedInEmployee); Task<ApiResponse<object>> GetNoteListByContactIdAsync(Guid id, bool active, Guid tenantId, Employee loggedInEmployee);
Task<ApiResponse<object>> GetContactNotesFilterObjectAsync(Guid tenantId, Employee loggedInEmployee); Task<ApiResponse<object>> GetContactNotesFilterObjectAsync(Guid tenantId, Employee loggedInEmployee);
Task<ApiResponse<object>> CreateContactNoteAsync(CreateContactNoteDto noteDto, Guid tenantId, Employee loggedInEmployee); Task<ApiResponse<object>> CreateContactNoteAsync(CreateContactNoteDto noteDto, Guid tenantId, Employee loggedInEmployee);